From 29e3605576f057feb668d8aa1b6d3d0c79c34207 Mon Sep 17 00:00:00 2001 From: Kyle Spearrin Date: Fri, 3 Mar 2017 00:07:11 -0500 Subject: [PATCH] organization signup apis and data model changes --- .../Controllers/OrganizationsController.cs | 26 +++- .../OrganizationCreateRequestModel.cs | 16 +-- .../Models/Response/DomainsResponseModel.cs | 4 +- .../Response/OrganizationResponseModel.cs | 27 +++- src/Api/Startup.cs | 1 + src/Core/Domains/Organization.cs | 7 +- src/Core/Enums/PlanType.cs | 3 +- .../Models/Business/OrganizationSignup.cs | 20 +++ src/Core/Models/StaticStore/Plan.cs | 15 ++ .../IOrganizationUserRepository.cs | 2 +- .../SqlServer/OrganizationUserRepository.cs | 4 +- src/Core/Services/IOrganizationService.cs | 12 ++ .../Implementations/OrganizationService.cs | 83 +++++++++++ src/Core/Utilities/EquivalentDomains.cs | 88 ------------ src/Core/Utilities/StaticStore.cs | 130 ++++++++++++++++++ src/Sql/Sql.sqlproj | 10 +- ...zationUser_ReadByOrganizationIdUserId.sql} | 6 +- .../Stored Procedures/Organization_Create.sql | 17 ++- .../Stored Procedures/Organization_Update.sql | 12 +- src/Sql/dbo/Tables/Organization.sql | 19 ++- 20 files changed, 371 insertions(+), 131 deletions(-) create mode 100644 src/Core/Models/Business/OrganizationSignup.cs create mode 100644 src/Core/Models/StaticStore/Plan.cs create mode 100644 src/Core/Services/IOrganizationService.cs create mode 100644 src/Core/Services/Implementations/OrganizationService.cs delete mode 100644 src/Core/Utilities/EquivalentDomains.cs create mode 100644 src/Core/Utilities/StaticStore.cs rename src/Sql/dbo/Stored Procedures/{OrganizationUser_ReadByIdUserId.sql => OrganizationUser_ReadByOrganizationIdUserId.sql} (52%) diff --git a/src/Api/Controllers/OrganizationsController.cs b/src/Api/Controllers/OrganizationsController.cs index 4716a9a054..e514c2a942 100644 --- a/src/Api/Controllers/OrganizationsController.cs +++ b/src/Api/Controllers/OrganizationsController.cs @@ -15,18 +15,24 @@ namespace Bit.Api.Controllers public class OrganizationsController : Controller { private readonly IOrganizationRepository _organizationRepository; + private readonly IOrganizationUserRepository _organizationUserRepository; + private readonly IOrganizationService _organizationService; private readonly IUserService _userService; public OrganizationsController( IOrganizationRepository organizationRepository, + IOrganizationUserRepository organizationUserRepository, + IOrganizationService organizationService, IUserService userService) { _organizationRepository = organizationRepository; + _organizationUserRepository = organizationUserRepository; + _organizationService = organizationService; _userService = userService; } [HttpGet("{id}")] - public async Task Get(string id) + public async Task Get(string id) { var userId = _userService.GetProperUserId(User).Value; var organization = await _organizationRepository.GetByIdAsync(new Guid(id), userId); @@ -35,7 +41,13 @@ namespace Bit.Api.Controllers throw new NotFoundException(); } - return new OrganizationResponseModel(organization); + var organizationUser = await _organizationUserRepository.GetByOrganizationAsync(new Guid(id), userId); + if(organizationUser == null) + { + throw new NotFoundException(); + } + + return new OrganizationExtendedResponseModel(organization, organizationUser); } [HttpGet("")] @@ -48,12 +60,12 @@ namespace Bit.Api.Controllers } [HttpPost("")] - public async Task Post([FromBody]OrganizationCreateRequestModel model) + public async Task Post([FromBody]OrganizationCreateRequestModel model) { - var userId = _userService.GetProperUserId(User).Value; - var organization = model.ToOrganization(_userService.GetProperUserId(User).Value); - await _organizationRepository.ReplaceAsync(organization); - return new OrganizationResponseModel(organization); + var user = await _userService.GetUserByPrincipalAsync(User); + var organizationSignup = model.ToOrganizationSignup(user); + var result = await _organizationService.SignUpAsync(organizationSignup); + return new OrganizationExtendedResponseModel(result.Item1, result.Item2); } [HttpPut("{id}")] diff --git a/src/Api/Models/Request/Organizations/OrganizationCreateRequestModel.cs b/src/Api/Models/Request/Organizations/OrganizationCreateRequestModel.cs index a70a5b635c..d81dc6969e 100644 --- a/src/Api/Models/Request/Organizations/OrganizationCreateRequestModel.cs +++ b/src/Api/Models/Request/Organizations/OrganizationCreateRequestModel.cs @@ -1,5 +1,6 @@ using Bit.Core.Domains; using Bit.Core.Enums; +using Bit.Core.Models.Business; using System; namespace Bit.Api.Models @@ -7,19 +8,18 @@ namespace Bit.Api.Models public class OrganizationCreateRequestModel { public string Name { get; set; } - public PlanType Plan { get; set; } - // TODO: Billing info for paid plans. + public PlanType PlanType { get; set; } + public string Key { get; set; } - public virtual Organization ToOrganization(Guid userId) + public virtual OrganizationSignup ToOrganizationSignup(User user) { - var organization = new Organization + return new OrganizationSignup { - UserId = userId, + Owner = user, + OwnerKey = Key, Name = Name, - Plan = Plan + Plan = PlanType }; - - return organization; } } } diff --git a/src/Api/Models/Response/DomainsResponseModel.cs b/src/Api/Models/Response/DomainsResponseModel.cs index 60404e3a2e..7d5e1686fa 100644 --- a/src/Api/Models/Response/DomainsResponseModel.cs +++ b/src/Api/Models/Response/DomainsResponseModel.cs @@ -24,8 +24,8 @@ namespace Bit.Api.Models JsonConvert.DeserializeObject>(user.ExcludedGlobalEquivalentDomains) : new List(); var globalDomains = new List(); - var domainsToInclude = excluded ? Core.Utilities.EquivalentDomains.Global : - Core.Utilities.EquivalentDomains.Global.Where(d => !excludedGlobalEquivalentDomains.Contains(d.Key)); + var domainsToInclude = excluded ? Core.Utilities.StaticStore.GlobalDomains : + Core.Utilities.StaticStore.GlobalDomains.Where(d => !excludedGlobalEquivalentDomains.Contains(d.Key)); foreach(var domain in domainsToInclude) { globalDomains.Add(new GlobalDomains(domain.Key, domain.Value, excludedGlobalEquivalentDomains, excluded)); diff --git a/src/Api/Models/Response/OrganizationResponseModel.cs b/src/Api/Models/Response/OrganizationResponseModel.cs index 3ab57f0d1a..7b7d41aa0f 100644 --- a/src/Api/Models/Response/OrganizationResponseModel.cs +++ b/src/Api/Models/Response/OrganizationResponseModel.cs @@ -1,13 +1,12 @@ using System; using Bit.Core.Domains; -using Bit.Core.Enums; namespace Bit.Api.Models { public class OrganizationResponseModel : ResponseModel { - public OrganizationResponseModel(Organization organization) - : base("organization") + public OrganizationResponseModel(Organization organization, string obj = "organization") + : base(obj) { if(organization == null) { @@ -17,12 +16,32 @@ namespace Bit.Api.Models Id = organization.Id.ToString(); Name = organization.Name; Plan = organization.Plan; + PlanType = organization.PlanType; + PlanTrial = organization.PlanTrial; MaxUsers = organization.MaxUsers; } public string Id { get; set; } public string Name { get; set; } - public PlanType Plan { get; set; } + public string Plan { get; set; } + public Core.Enums.PlanType PlanType { get; set; } + public bool PlanTrial { get; set; } public short MaxUsers { get; set; } } + + public class OrganizationExtendedResponseModel : OrganizationResponseModel + { + public OrganizationExtendedResponseModel(Organization organization, OrganizationUser organizationUser) + : base(organization, "organizationExtended") + { + if(organizationUser == null) + { + throw new ArgumentNullException(nameof(organizationUser)); + } + + Key = organizationUser.Key; + } + + public string Key { get; set; } + } } diff --git a/src/Api/Startup.cs b/src/Api/Startup.cs index ea69ce2454..506851e588 100644 --- a/src/Api/Startup.cs +++ b/src/Api/Startup.cs @@ -180,6 +180,7 @@ namespace Bit.Api services.AddScoped(); services.AddScoped(); services.AddScoped(); + services.AddScoped(); // Cors services.AddCors(config => diff --git a/src/Core/Domains/Organization.cs b/src/Core/Domains/Organization.cs index 1038263f9b..39f67b0427 100644 --- a/src/Core/Domains/Organization.cs +++ b/src/Core/Domains/Organization.cs @@ -9,7 +9,12 @@ namespace Bit.Core.Domains public Guid Id { get; set; } public Guid UserId { get; set; } public string Name { get; set; } - public PlanType Plan { get; set; } + public string Plan { get; set; } + public PlanType PlanType { get; set; } + public decimal PlanPrice { get; set; } + public decimal PlanRenewalPrice { get; set; } + public DateTime? PlanRenewalDate { get; set; } + public bool PlanTrial { get; set; } public short MaxUsers { get; set; } public DateTime CreationDate { get; internal set; } = DateTime.UtcNow; public DateTime RevisionDate { get; internal set; } = DateTime.UtcNow; diff --git a/src/Core/Enums/PlanType.cs b/src/Core/Enums/PlanType.cs index 4288aa8282..64bef70fec 100644 --- a/src/Core/Enums/PlanType.cs +++ b/src/Core/Enums/PlanType.cs @@ -5,6 +5,7 @@ Free = 0, Family = 1, Teams = 2, - Enterprise = 3 + Enterprise = 3, + Custom = 4 } } diff --git a/src/Core/Models/Business/OrganizationSignup.cs b/src/Core/Models/Business/OrganizationSignup.cs new file mode 100644 index 0000000000..09b724dbd6 --- /dev/null +++ b/src/Core/Models/Business/OrganizationSignup.cs @@ -0,0 +1,20 @@ +using Bit.Core.Domains; +using System; + +namespace Bit.Core.Models.Business +{ + public class OrganizationSignup + { + public string Name { get; set; } + public User Owner { get; set; } + public string OwnerKey { get; set; } + public Enums.PlanType Plan { get; set; } + public PaymentDetails Payment { get; set; } + + public class PaymentDetails + { + public string Name { get; set; } + public string Token { get; set; } + } + } +} diff --git a/src/Core/Models/StaticStore/Plan.cs b/src/Core/Models/StaticStore/Plan.cs new file mode 100644 index 0000000000..4bcbb11b23 --- /dev/null +++ b/src/Core/Models/StaticStore/Plan.cs @@ -0,0 +1,15 @@ +using Bit.Core.Enums; +using System; + +namespace Bit.Core.Models.StaticStore +{ + public class Plan + { + public PlanType Type { get; set; } + public short MaxUsers { get; set; } + public decimal Price { get; set; } + public TimeSpan? Trial { get; set; } + public Func Cycle { get; set; } + public bool Disabled { get; set; } + } +} diff --git a/src/Core/Repositories/IOrganizationUserRepository.cs b/src/Core/Repositories/IOrganizationUserRepository.cs index 6e31adc93e..2f47d316a3 100644 --- a/src/Core/Repositories/IOrganizationUserRepository.cs +++ b/src/Core/Repositories/IOrganizationUserRepository.cs @@ -7,6 +7,6 @@ namespace Bit.Core.Repositories { public interface IOrganizationUserRepository : IRepository { - Task GetByIdAsync(Guid id, Guid userId); + Task GetByOrganizationAsync(Guid organizationId, Guid userId); } } diff --git a/src/Core/Repositories/SqlServer/OrganizationUserRepository.cs b/src/Core/Repositories/SqlServer/OrganizationUserRepository.cs index d3f1cc89c6..5c1864631b 100644 --- a/src/Core/Repositories/SqlServer/OrganizationUserRepository.cs +++ b/src/Core/Repositories/SqlServer/OrganizationUserRepository.cs @@ -18,13 +18,13 @@ namespace Bit.Core.Repositories.SqlServer : base(connectionString) { } - public async Task GetByIdAsync(Guid id, Guid userId) + public async Task GetByOrganizationAsync(Guid organizationId, Guid userId) { using(var connection = new SqlConnection(ConnectionString)) { var results = await connection.QueryAsync( "[dbo].[OrganizationUser_ReadByIdUserId]", - new { Id = id, UserId = userId }, + new { OrganizationId = organizationId, UserId = userId }, commandType: CommandType.StoredProcedure); return results.SingleOrDefault(); diff --git a/src/Core/Services/IOrganizationService.cs b/src/Core/Services/IOrganizationService.cs new file mode 100644 index 0000000000..24b6ea6fc2 --- /dev/null +++ b/src/Core/Services/IOrganizationService.cs @@ -0,0 +1,12 @@ +using System.Threading.Tasks; +using Bit.Core.Models.Business; +using Bit.Core.Domains; +using System; + +namespace Bit.Core.Services +{ + public interface IOrganizationService + { + Task> SignUpAsync(OrganizationSignup organizationSignup); + } +} diff --git a/src/Core/Services/Implementations/OrganizationService.cs b/src/Core/Services/Implementations/OrganizationService.cs new file mode 100644 index 0000000000..c00be0b85c --- /dev/null +++ b/src/Core/Services/Implementations/OrganizationService.cs @@ -0,0 +1,83 @@ +using System; +using System.Linq; +using System.Threading.Tasks; +using Bit.Core.Repositories; +using Bit.Core.Models.Business; +using Bit.Core.Domains; +using Bit.Core.Utilities; +using Bit.Core.Exceptions; + +namespace Bit.Core.Services +{ + public class OrganizationService : IOrganizationService + { + private readonly IOrganizationRepository _organizationRepository; + private readonly IOrganizationUserRepository _organizationUserRepository; + + public OrganizationService( + IOrganizationRepository organizationRepository, + IOrganizationUserRepository organizationUserRepository) + { + _organizationRepository = organizationRepository; + _organizationUserRepository = organizationUserRepository; + } + + public async Task> SignUpAsync(OrganizationSignup organizationSignup) + { + var plan = StaticStore.Plans.FirstOrDefault(p => p.Type == organizationSignup.Plan); + if(plan == null) + { + throw new BadRequestException("Plan not found."); + } + + var organization = new Organization + { + Name = organizationSignup.Name, + UserId = organizationSignup.Owner.Id, + PlanType = plan.Type, + MaxUsers = plan.MaxUsers, + PlanTrial = plan.Trial.HasValue, + PlanPrice = plan.Trial.HasValue ? 0 : plan.Price, + PlanRenewalPrice = plan.Price, + Plan = plan.ToString(), + CreationDate = DateTime.UtcNow, + RevisionDate = DateTime.UtcNow + }; + + if(plan.Trial.HasValue) + { + organization.PlanRenewalDate = DateTime.UtcNow.Add(plan.Trial.Value); + } + else if(plan.Cycle != null) + { + organization.PlanRenewalDate = DateTime.UtcNow.Add(plan.Cycle()); + } + + await _organizationRepository.CreateAsync(organization); + + try + { + var orgUser = new OrganizationUser + { + OrganizationId = organization.Id, + UserId = organizationSignup.Owner.Id, + Email = organizationSignup.Owner.Email, + Key = organizationSignup.OwnerKey, + Type = Enums.OrganizationUserType.Owner, + Status = Enums.OrganizationUserStatusType.Confirmed, + CreationDate = DateTime.UtcNow, + RevisionDate = DateTime.UtcNow + }; + + await _organizationUserRepository.CreateAsync(orgUser); + + return new Tuple(organization, orgUser); + } + catch + { + await _organizationRepository.DeleteAsync(organization); + throw; + } + } + } +} diff --git a/src/Core/Utilities/EquivalentDomains.cs b/src/Core/Utilities/EquivalentDomains.cs deleted file mode 100644 index a2716981f2..0000000000 --- a/src/Core/Utilities/EquivalentDomains.cs +++ /dev/null @@ -1,88 +0,0 @@ -using Bit.Core.Enums; -using System.Collections.Generic; - -namespace Bit.Core.Utilities -{ - public class EquivalentDomains - { - static EquivalentDomains() - { - Global = new Dictionary>(); - - Global.Add(GlobalEquivalentDomainsType.Ameritrade, new List { "ameritrade.com", "tdameritrade.com" }); - Global.Add(GlobalEquivalentDomainsType.BoA, new List { "bankofamerica.com", "bofa.com", "mbna.com", "usecfo.com" }); - Global.Add(GlobalEquivalentDomainsType.Sprint, new List { "sprint.com", "sprintpcs.com", "nextel.com" }); - Global.Add(GlobalEquivalentDomainsType.Google, new List { "youtube.com", "google.com", "gmail.com" }); - Global.Add(GlobalEquivalentDomainsType.Apple, new List { "apple.com", "icloud.com" }); - Global.Add(GlobalEquivalentDomainsType.WellsFargo, new List { "wellsfargo.com", "wf.com" }); - Global.Add(GlobalEquivalentDomainsType.Merrill, new List { "mymerrill.com", "ml.com", "merrilledge.com" }); - Global.Add(GlobalEquivalentDomainsType.Citi, new List { "accountonline.com", "citi.com", "citibank.com", "citicards.com", "citibankonline.com" }); - Global.Add(GlobalEquivalentDomainsType.Cnet, new List { "cnet.com", "cnettv.com", "com.com", "download.com", "news.com", "search.com", "upload.com" }); - Global.Add(GlobalEquivalentDomainsType.Gap, new List { "bananarepublic.com", "gap.com", "oldnavy.com", "piperlime.com" }); - Global.Add(GlobalEquivalentDomainsType.Microsoft, new List { "bing.com", "hotmail.com", "live.com", "microsoft.com", "msn.com", "passport.net", "windows.com", "microsoftonline.com" }); - Global.Add(GlobalEquivalentDomainsType.United, new List { "ua2go.com", "ual.com", "united.com", "unitedwifi.com" }); - Global.Add(GlobalEquivalentDomainsType.Yahoo, new List { "overture.com", "yahoo.com", "flickr.com" }); - Global.Add(GlobalEquivalentDomainsType.Zonelabs, new List { "zonealarm.com", "zonelabs.com" }); - Global.Add(GlobalEquivalentDomainsType.Paypal, new List { "paypal.com", "paypal-search.com" }); - Global.Add(GlobalEquivalentDomainsType.Avon, new List { "avon.com", "youravon.com" }); - Global.Add(GlobalEquivalentDomainsType.Diapers, new List { "diapers.com", "soap.com", "wag.com", "yoyo.com", "beautybar.com", "casa.com", "afterschool.com", "vine.com", "bookworm.com", "look.com", "vinemarket.com" }); - Global.Add(GlobalEquivalentDomainsType.Contacts, new List { "1800contacts.com", "800contacts.com" }); - Global.Add(GlobalEquivalentDomainsType.Amazon, new List { "amazon.com", "amazon.co.uk", "amazon.ca", "amazon.de", "amazon.fr", "amazon.es", "amazon.it", "amazon.com.au" }); - Global.Add(GlobalEquivalentDomainsType.Cox, new List { "cox.com", "cox.net", "coxbusiness.com" }); - Global.Add(GlobalEquivalentDomainsType.Norton, new List { "mynortonaccount.com", "norton.com" }); - Global.Add(GlobalEquivalentDomainsType.Verizon, new List { "verizon.com", "verizon.net" }); - Global.Add(GlobalEquivalentDomainsType.Buy, new List { "rakuten.com", "buy.com" }); - Global.Add(GlobalEquivalentDomainsType.Sirius, new List { "siriusxm.com", "sirius.com" }); - Global.Add(GlobalEquivalentDomainsType.Ea, new List { "ea.com", "origin.com", "play4free.com", "tiberiumalliance.com" }); - Global.Add(GlobalEquivalentDomainsType.Basecamp, new List { "37signals.com", "basecamp.com", "basecamphq.com", "highrisehq.com" }); - Global.Add(GlobalEquivalentDomainsType.Steam, new List { "steampowered.com", "steamcommunity.com" }); - Global.Add(GlobalEquivalentDomainsType.Chart, new List { "chart.io", "chartio.com" }); - Global.Add(GlobalEquivalentDomainsType.Gotomeeting, new List { "gotomeeting.com", "citrixonline.com" }); - Global.Add(GlobalEquivalentDomainsType.Gogo, new List { "gogoair.com", "gogoinflight.com" }); - Global.Add(GlobalEquivalentDomainsType.Oracle, new List { "mysql.com", "oracle.com" }); - Global.Add(GlobalEquivalentDomainsType.Discover, new List { "discover.com", "discovercard.com" }); - Global.Add(GlobalEquivalentDomainsType.Dcu, new List { "dcu.org", "dcu-online.org" }); - Global.Add(GlobalEquivalentDomainsType.Healthcare, new List { "healthcare.gov", "cms.gov" }); - Global.Add(GlobalEquivalentDomainsType.Pepco, new List { "pepco.com", "pepcoholdings.com" }); - Global.Add(GlobalEquivalentDomainsType.Century21, new List { "century21.com", "21online.com" }); - Global.Add(GlobalEquivalentDomainsType.Comcast, new List { "comcast.com", "comcast.net", "xfinity.com" }); - Global.Add(GlobalEquivalentDomainsType.Cricket, new List { "cricketwireless.com", "aiowireless.com" }); - Global.Add(GlobalEquivalentDomainsType.Mtb, new List { "mandtbank.com", "mtb.com" }); - Global.Add(GlobalEquivalentDomainsType.Dropbox, new List { "dropbox.com", "getdropbox.com" }); - Global.Add(GlobalEquivalentDomainsType.Snapfish, new List { "snapfish.com", "snapfish.ca" }); - Global.Add(GlobalEquivalentDomainsType.Alibaba, new List { "alibaba.com", "aliexpress.com", "aliyun.com", "net.cn", "www.net.cn" }); - Global.Add(GlobalEquivalentDomainsType.Playstation, new List { "playstation.com", "sonyentertainmentnetwork.com" }); - Global.Add(GlobalEquivalentDomainsType.Mercado, new List { "mercadolivre.com", "mercadolivre.com.br", "mercadolibre.com", "mercadolibre.com.ar", "mercadolibre.com.mx" }); - Global.Add(GlobalEquivalentDomainsType.Zendesk, new List { "zendesk.com", "zopim.com" }); - Global.Add(GlobalEquivalentDomainsType.Autodesk, new List { "autodesk.com", "tinkercad.com" }); - Global.Add(GlobalEquivalentDomainsType.RailNation, new List { "railnation.ru", "railnation.de", "rail-nation.com", "railnation.gr", "railnation.us", "trucknation.de", "traviangames.com" }); - Global.Add(GlobalEquivalentDomainsType.Wpcu, new List { "wpcu.coop", "wpcuonline.com" }); - Global.Add(GlobalEquivalentDomainsType.Mathletics, new List { "mathletics.com", "mathletics.com.au", "mathletics.co.uk" }); - Global.Add(GlobalEquivalentDomainsType.Discountbank, new List { "discountbank.co.il", "telebank.co.il" }); - Global.Add(GlobalEquivalentDomainsType.Mi, new List { "mi.com", "xiaomi.com" }); - Global.Add(GlobalEquivalentDomainsType.Postepay, new List { "postepay.it", "poste.it" }); - Global.Add(GlobalEquivalentDomainsType.Facebook, new List { "facebook.com", "messenger.com" }); - Global.Add(GlobalEquivalentDomainsType.Skysports, new List { "skysports.com", "skybet.com", "skyvegas.com" }); - Global.Add(GlobalEquivalentDomainsType.Disney, new List { "disneymoviesanywhere.com", "go.com", "disney.com", "dadt.com" }); - Global.Add(GlobalEquivalentDomainsType.Pokemon, new List { "pokemon-gl.com", "pokemon.com" }); - Global.Add(GlobalEquivalentDomainsType.Uv, new List { "myuv.com", "uvvu.com" }); - Global.Add(GlobalEquivalentDomainsType.Mdsol, new List { "mdsol.com", "imedidata.com" }); - Global.Add(GlobalEquivalentDomainsType.Yahavo, new List { "bank-yahav.co.il", "bankhapoalim.co.il" }); - Global.Add(GlobalEquivalentDomainsType.Sears, new List { "sears.com", "shld.net" }); - Global.Add(GlobalEquivalentDomainsType.Xiami, new List { "xiami.com", "alipay.com" }); - Global.Add(GlobalEquivalentDomainsType.Belkin, new List { "belkin.com", "seedonk.com" }); - Global.Add(GlobalEquivalentDomainsType.Turbotax, new List { "turbotax.com", "intuit.com" }); - Global.Add(GlobalEquivalentDomainsType.Shopify, new List { "shopify.com", "myshopify.com" }); - Global.Add(GlobalEquivalentDomainsType.Ebay, new List { "ebay.com", "ebay.de", "ebay.ca", "ebay.in", "ebay.co.uk", "ebay.com.au" }); - Global.Add(GlobalEquivalentDomainsType.Techdata, new List { "techdata.com", "techdata.ch" }); - Global.Add(GlobalEquivalentDomainsType.Schwab, new List { "schwab.com", "schwabplan.com" }); - Global.Add(GlobalEquivalentDomainsType.Mozilla, new List { "firefox.com", "mozilla.org" }); - Global.Add(GlobalEquivalentDomainsType.Tesla, new List { "tesla.com", "teslamotors.com" }); - Global.Add(GlobalEquivalentDomainsType.MorganStanley, new List { "morganstanley.com", "morganstanleyclientserv.com", "stockplanconnect.com", "ms.com" }); - Global.Add(GlobalEquivalentDomainsType.TaxAct, new List { "taxact.com", "taxactonline.com" }); - } - - public static IDictionary> Global { get; set; } - - } -} diff --git a/src/Core/Utilities/StaticStore.cs b/src/Core/Utilities/StaticStore.cs new file mode 100644 index 0000000000..9d10328999 --- /dev/null +++ b/src/Core/Utilities/StaticStore.cs @@ -0,0 +1,130 @@ +using Bit.Core.Enums; +using Bit.Core.Models.StaticStore; +using System; +using System.Collections.Generic; + +namespace Bit.Core.Utilities +{ + public class StaticStore + { + static StaticStore() + { + #region Global Domains + + GlobalDomains = new Dictionary>(); + + GlobalDomains.Add(GlobalEquivalentDomainsType.Ameritrade, new List { "ameritrade.com", "tdameritrade.com" }); + GlobalDomains.Add(GlobalEquivalentDomainsType.BoA, new List { "bankofamerica.com", "bofa.com", "mbna.com", "usecfo.com" }); + GlobalDomains.Add(GlobalEquivalentDomainsType.Sprint, new List { "sprint.com", "sprintpcs.com", "nextel.com" }); + GlobalDomains.Add(GlobalEquivalentDomainsType.Google, new List { "youtube.com", "google.com", "gmail.com" }); + GlobalDomains.Add(GlobalEquivalentDomainsType.Apple, new List { "apple.com", "icloud.com" }); + GlobalDomains.Add(GlobalEquivalentDomainsType.WellsFargo, new List { "wellsfargo.com", "wf.com" }); + GlobalDomains.Add(GlobalEquivalentDomainsType.Merrill, new List { "mymerrill.com", "ml.com", "merrilledge.com" }); + GlobalDomains.Add(GlobalEquivalentDomainsType.Citi, new List { "accountonline.com", "citi.com", "citibank.com", "citicards.com", "citibankonline.com" }); + GlobalDomains.Add(GlobalEquivalentDomainsType.Cnet, new List { "cnet.com", "cnettv.com", "com.com", "download.com", "news.com", "search.com", "upload.com" }); + GlobalDomains.Add(GlobalEquivalentDomainsType.Gap, new List { "bananarepublic.com", "gap.com", "oldnavy.com", "piperlime.com" }); + GlobalDomains.Add(GlobalEquivalentDomainsType.Microsoft, new List { "bing.com", "hotmail.com", "live.com", "microsoft.com", "msn.com", "passport.net", "windows.com", "microsoftonline.com" }); + GlobalDomains.Add(GlobalEquivalentDomainsType.United, new List { "ua2go.com", "ual.com", "united.com", "unitedwifi.com" }); + GlobalDomains.Add(GlobalEquivalentDomainsType.Yahoo, new List { "overture.com", "yahoo.com", "flickr.com" }); + GlobalDomains.Add(GlobalEquivalentDomainsType.Zonelabs, new List { "zonealarm.com", "zonelabs.com" }); + GlobalDomains.Add(GlobalEquivalentDomainsType.Paypal, new List { "paypal.com", "paypal-search.com" }); + GlobalDomains.Add(GlobalEquivalentDomainsType.Avon, new List { "avon.com", "youravon.com" }); + GlobalDomains.Add(GlobalEquivalentDomainsType.Diapers, new List { "diapers.com", "soap.com", "wag.com", "yoyo.com", "beautybar.com", "casa.com", "afterschool.com", "vine.com", "bookworm.com", "look.com", "vinemarket.com" }); + GlobalDomains.Add(GlobalEquivalentDomainsType.Contacts, new List { "1800contacts.com", "800contacts.com" }); + GlobalDomains.Add(GlobalEquivalentDomainsType.Amazon, new List { "amazon.com", "amazon.co.uk", "amazon.ca", "amazon.de", "amazon.fr", "amazon.es", "amazon.it", "amazon.com.au" }); + GlobalDomains.Add(GlobalEquivalentDomainsType.Cox, new List { "cox.com", "cox.net", "coxbusiness.com" }); + GlobalDomains.Add(GlobalEquivalentDomainsType.Norton, new List { "mynortonaccount.com", "norton.com" }); + GlobalDomains.Add(GlobalEquivalentDomainsType.Verizon, new List { "verizon.com", "verizon.net" }); + GlobalDomains.Add(GlobalEquivalentDomainsType.Buy, new List { "rakuten.com", "buy.com" }); + GlobalDomains.Add(GlobalEquivalentDomainsType.Sirius, new List { "siriusxm.com", "sirius.com" }); + GlobalDomains.Add(GlobalEquivalentDomainsType.Ea, new List { "ea.com", "origin.com", "play4free.com", "tiberiumalliance.com" }); + GlobalDomains.Add(GlobalEquivalentDomainsType.Basecamp, new List { "37signals.com", "basecamp.com", "basecamphq.com", "highrisehq.com" }); + GlobalDomains.Add(GlobalEquivalentDomainsType.Steam, new List { "steampowered.com", "steamcommunity.com" }); + GlobalDomains.Add(GlobalEquivalentDomainsType.Chart, new List { "chart.io", "chartio.com" }); + GlobalDomains.Add(GlobalEquivalentDomainsType.Gotomeeting, new List { "gotomeeting.com", "citrixonline.com" }); + GlobalDomains.Add(GlobalEquivalentDomainsType.Gogo, new List { "gogoair.com", "gogoinflight.com" }); + GlobalDomains.Add(GlobalEquivalentDomainsType.Oracle, new List { "mysql.com", "oracle.com" }); + GlobalDomains.Add(GlobalEquivalentDomainsType.Discover, new List { "discover.com", "discovercard.com" }); + GlobalDomains.Add(GlobalEquivalentDomainsType.Dcu, new List { "dcu.org", "dcu-online.org" }); + GlobalDomains.Add(GlobalEquivalentDomainsType.Healthcare, new List { "healthcare.gov", "cms.gov" }); + GlobalDomains.Add(GlobalEquivalentDomainsType.Pepco, new List { "pepco.com", "pepcoholdings.com" }); + GlobalDomains.Add(GlobalEquivalentDomainsType.Century21, new List { "century21.com", "21online.com" }); + GlobalDomains.Add(GlobalEquivalentDomainsType.Comcast, new List { "comcast.com", "comcast.net", "xfinity.com" }); + GlobalDomains.Add(GlobalEquivalentDomainsType.Cricket, new List { "cricketwireless.com", "aiowireless.com" }); + GlobalDomains.Add(GlobalEquivalentDomainsType.Mtb, new List { "mandtbank.com", "mtb.com" }); + GlobalDomains.Add(GlobalEquivalentDomainsType.Dropbox, new List { "dropbox.com", "getdropbox.com" }); + GlobalDomains.Add(GlobalEquivalentDomainsType.Snapfish, new List { "snapfish.com", "snapfish.ca" }); + GlobalDomains.Add(GlobalEquivalentDomainsType.Alibaba, new List { "alibaba.com", "aliexpress.com", "aliyun.com", "net.cn", "www.net.cn" }); + GlobalDomains.Add(GlobalEquivalentDomainsType.Playstation, new List { "playstation.com", "sonyentertainmentnetwork.com" }); + GlobalDomains.Add(GlobalEquivalentDomainsType.Mercado, new List { "mercadolivre.com", "mercadolivre.com.br", "mercadolibre.com", "mercadolibre.com.ar", "mercadolibre.com.mx" }); + GlobalDomains.Add(GlobalEquivalentDomainsType.Zendesk, new List { "zendesk.com", "zopim.com" }); + GlobalDomains.Add(GlobalEquivalentDomainsType.Autodesk, new List { "autodesk.com", "tinkercad.com" }); + GlobalDomains.Add(GlobalEquivalentDomainsType.RailNation, new List { "railnation.ru", "railnation.de", "rail-nation.com", "railnation.gr", "railnation.us", "trucknation.de", "traviangames.com" }); + GlobalDomains.Add(GlobalEquivalentDomainsType.Wpcu, new List { "wpcu.coop", "wpcuonline.com" }); + GlobalDomains.Add(GlobalEquivalentDomainsType.Mathletics, new List { "mathletics.com", "mathletics.com.au", "mathletics.co.uk" }); + GlobalDomains.Add(GlobalEquivalentDomainsType.Discountbank, new List { "discountbank.co.il", "telebank.co.il" }); + GlobalDomains.Add(GlobalEquivalentDomainsType.Mi, new List { "mi.com", "xiaomi.com" }); + GlobalDomains.Add(GlobalEquivalentDomainsType.Postepay, new List { "postepay.it", "poste.it" }); + GlobalDomains.Add(GlobalEquivalentDomainsType.Facebook, new List { "facebook.com", "messenger.com" }); + GlobalDomains.Add(GlobalEquivalentDomainsType.Skysports, new List { "skysports.com", "skybet.com", "skyvegas.com" }); + GlobalDomains.Add(GlobalEquivalentDomainsType.Disney, new List { "disneymoviesanywhere.com", "go.com", "disney.com", "dadt.com" }); + GlobalDomains.Add(GlobalEquivalentDomainsType.Pokemon, new List { "pokemon-gl.com", "pokemon.com" }); + GlobalDomains.Add(GlobalEquivalentDomainsType.Uv, new List { "myuv.com", "uvvu.com" }); + GlobalDomains.Add(GlobalEquivalentDomainsType.Mdsol, new List { "mdsol.com", "imedidata.com" }); + GlobalDomains.Add(GlobalEquivalentDomainsType.Yahavo, new List { "bank-yahav.co.il", "bankhapoalim.co.il" }); + GlobalDomains.Add(GlobalEquivalentDomainsType.Sears, new List { "sears.com", "shld.net" }); + GlobalDomains.Add(GlobalEquivalentDomainsType.Xiami, new List { "xiami.com", "alipay.com" }); + GlobalDomains.Add(GlobalEquivalentDomainsType.Belkin, new List { "belkin.com", "seedonk.com" }); + GlobalDomains.Add(GlobalEquivalentDomainsType.Turbotax, new List { "turbotax.com", "intuit.com" }); + GlobalDomains.Add(GlobalEquivalentDomainsType.Shopify, new List { "shopify.com", "myshopify.com" }); + GlobalDomains.Add(GlobalEquivalentDomainsType.Ebay, new List { "ebay.com", "ebay.de", "ebay.ca", "ebay.in", "ebay.co.uk", "ebay.com.au" }); + GlobalDomains.Add(GlobalEquivalentDomainsType.Techdata, new List { "techdata.com", "techdata.ch" }); + GlobalDomains.Add(GlobalEquivalentDomainsType.Schwab, new List { "schwab.com", "schwabplan.com" }); + GlobalDomains.Add(GlobalEquivalentDomainsType.Mozilla, new List { "firefox.com", "mozilla.org" }); + GlobalDomains.Add(GlobalEquivalentDomainsType.Tesla, new List { "tesla.com", "teslamotors.com" }); + GlobalDomains.Add(GlobalEquivalentDomainsType.MorganStanley, new List { "morganstanley.com", "morganstanleyclientserv.com", "stockplanconnect.com", "ms.com" }); + GlobalDomains.Add(GlobalEquivalentDomainsType.TaxAct, new List { "taxact.com", "taxactonline.com" }); + + #endregion + + #region Plans + + Plans = new List + { + new Plan + { + Type = PlanType.Free, + MaxUsers = 1, + Price = 0 + }, + new Plan + { + Type = PlanType.Family, + MaxUsers = 5, + Price = 1, + Trial = new TimeSpan(14, 0, 0, 0), + Cycle = () => { + var now = DateTime.Now; + return now.AddYears(1) - now; + } + }, + new Plan + { + Type = PlanType.Teams, + MaxUsers = 5, + Price = 10, + Trial = new TimeSpan(14, 0, 0, 0), + Cycle = () => { + var now = DateTime.Now; + return now.AddMonths(1) - now; + } + } + }; + + #endregion + } + + public static IDictionary> GlobalDomains { get; set; } + public static IEnumerable Plans { get; set; } + } +} diff --git a/src/Sql/Sql.sqlproj b/src/Sql/Sql.sqlproj index 60ea22d62d..08c7d3cfac 100644 --- a/src/Sql/Sql.sqlproj +++ b/src/Sql/Sql.sqlproj @@ -81,6 +81,8 @@ + + @@ -130,17 +132,15 @@ + + + - - - - - \ No newline at end of file diff --git a/src/Sql/dbo/Stored Procedures/OrganizationUser_ReadByIdUserId.sql b/src/Sql/dbo/Stored Procedures/OrganizationUser_ReadByOrganizationIdUserId.sql similarity index 52% rename from src/Sql/dbo/Stored Procedures/OrganizationUser_ReadByIdUserId.sql rename to src/Sql/dbo/Stored Procedures/OrganizationUser_ReadByOrganizationIdUserId.sql index 8037bef365..96838916c7 100644 --- a/src/Sql/dbo/Stored Procedures/OrganizationUser_ReadByIdUserId.sql +++ b/src/Sql/dbo/Stored Procedures/OrganizationUser_ReadByOrganizationIdUserId.sql @@ -1,5 +1,5 @@ -CREATE PROCEDURE [dbo].[OrganizationUser_ReadByIdUserId] - @Id UNIQUEIDENTIFIER, +CREATE PROCEDURE [dbo].[OrganizationUser_ReadByOrganizationIdUserId] + @OrganizationId UNIQUEIDENTIFIER, @UserId UNIQUEIDENTIFIER AS BEGIN @@ -10,6 +10,6 @@ BEGIN FROM [dbo].[OrganizationUserView] WHERE - [Id] = @Id + [OrganizationId] = @OrganizationId AND [UserId] = @UserId END \ No newline at end of file diff --git a/src/Sql/dbo/Stored Procedures/Organization_Create.sql b/src/Sql/dbo/Stored Procedures/Organization_Create.sql index a85d495fda..844cce38e5 100644 --- a/src/Sql/dbo/Stored Procedures/Organization_Create.sql +++ b/src/Sql/dbo/Stored Procedures/Organization_Create.sql @@ -2,7 +2,12 @@ @Id UNIQUEIDENTIFIER, @UserId UNIQUEIDENTIFIER, @Name NVARCHAR(50), - @Plan TINYINT, + @Plan NVARCHAR(20), + @PlanType TINYINT, + @PlanPrice MONEY, + @PlanRenewalPrice MONEY, + @PlanRenewalDate DATETIME2(7), + @PlanTrial BIT, @MaxUsers SMALLINT, @CreationDate DATETIME2(7), @RevisionDate DATETIME2(7) @@ -16,6 +21,11 @@ BEGIN [UserId], [Name], [Plan], + [PlanType], + [PlanPrice], + [PlanRenewalPrice], + [PlanRenewalDate], + [PlanTrial], [MaxUsers], [CreationDate], [RevisionDate] @@ -26,6 +36,11 @@ BEGIN @UserId, @Name, @Plan, + @PlanType, + @PlanPrice, + @PlanRenewalPrice, + @PlanRenewalDate, + @PlanTrial, @MaxUsers, @CreationDate, @RevisionDate diff --git a/src/Sql/dbo/Stored Procedures/Organization_Update.sql b/src/Sql/dbo/Stored Procedures/Organization_Update.sql index 0b9663eedd..5ab985c967 100644 --- a/src/Sql/dbo/Stored Procedures/Organization_Update.sql +++ b/src/Sql/dbo/Stored Procedures/Organization_Update.sql @@ -2,7 +2,12 @@ @Id UNIQUEIDENTIFIER, @UserId UNIQUEIDENTIFIER, @Name NVARCHAR(50), - @Plan TINYINT, + @Plan NVARCHAR(20), + @PlanType TINYINT, + @PlanPrice MONEY, + @PlanRenewalPrice MONEY, + @PlanRenewalDate DATETIME2(7), + @PlanTrial BIT, @MaxUsers SMALLINT, @CreationDate DATETIME2(7), @RevisionDate DATETIME2(7) @@ -16,6 +21,11 @@ BEGIN [UserId] = @UserId, [Name] = @Name, [Plan] = @Plan, + [PlanType] = @PlanType, + [PlanPrice] = @PlanPrice, + [PlanRenewalPrice] = @PlanRenewalPrice, + [PlanRenewalDate] = @PlanRenewalDate, + [PlanTrial] = @PlanTrial, [MaxUsers] = @MaxUsers, [CreationDate] = @CreationDate, [RevisionDate] = @RevisionDate diff --git a/src/Sql/dbo/Tables/Organization.sql b/src/Sql/dbo/Tables/Organization.sql index 2f6652bf3f..03544dac6a 100644 --- a/src/Sql/dbo/Tables/Organization.sql +++ b/src/Sql/dbo/Tables/Organization.sql @@ -1,11 +1,16 @@ CREATE TABLE [dbo].[Organization] ( - [Id] UNIQUEIDENTIFIER NOT NULL, - [UserId] UNIQUEIDENTIFIER NOT NULL, - [Name] NVARCHAR (50) NOT NULL, - [Plan] TINYINT NOT NULL, - [MaxUsers] SMALLINT NULL, - [CreationDate] DATETIME2 (7) NOT NULL, - [RevisionDate] DATETIME2 (7) NOT NULL, + [Id] UNIQUEIDENTIFIER NOT NULL, + [UserId] UNIQUEIDENTIFIER NOT NULL, + [Name] NVARCHAR (50) NOT NULL, + [Plan] NVARCHAR (20) NOT NULL, + [PlanType] TINYINT NOT NULL, + [PlanPrice] MONEY NOT NULL, + [PlanRenewalPrice] MONEY NOT NULL, + [PlanRenewalDate] DATETIME2 (7) NULL, + [PlanTrial] BIT NOT NULL, + [MaxUsers] SMALLINT NULL, + [CreationDate] DATETIME2 (7) NOT NULL, + [RevisionDate] DATETIME2 (7) NOT NULL, CONSTRAINT [PK_Organization] PRIMARY KEY CLUSTERED ([Id] ASC), CONSTRAINT [FK_Organization_User] FOREIGN KEY ([UserId]) REFERENCES [dbo].[User] ([Id]) );