1
0
mirror of https://github.com/bitwarden/server.git synced 2025-07-04 09:32:48 -05:00

[AC-1284] AC Team code ownership moves - Provider (#3359)

This commit is contained in:
Thomas Rittson
2023-10-27 03:38:29 +10:00
committed by GitHub
parent c8bcc32764
commit 26dd8b0e47
115 changed files with 325 additions and 252 deletions

View File

@ -0,0 +1,22 @@
using Bit.Core.AdminConsole.Entities.Provider;
using Bit.Core.AdminConsole.Enums.Provider;
using Bit.Core.Models.Data;
using Bit.Core.Utilities;
namespace Bit.Core.AdminConsole.Context;
public class CurrentContextProvider
{
public CurrentContextProvider() { }
public CurrentContextProvider(ProviderUser providerUser)
{
Id = providerUser.ProviderId;
Type = providerUser.Type;
Permissions = CoreHelpers.LoadClassFromJsonData<Permissions>(providerUser.Permissions);
}
public Guid Id { get; set; }
public ProviderUserType Type { get; set; }
public Permissions Permissions { get; set; }
}

View File

@ -0,0 +1,33 @@
using Bit.Core.AdminConsole.Enums.Provider;
using Bit.Core.Entities;
using Bit.Core.Utilities;
namespace Bit.Core.AdminConsole.Entities.Provider;
public class Provider : ITableObject<Guid>
{
public Guid Id { get; set; }
public string Name { get; set; }
public string BusinessName { get; set; }
public string BusinessAddress1 { get; set; }
public string BusinessAddress2 { get; set; }
public string BusinessAddress3 { get; set; }
public string BusinessCountry { get; set; }
public string BusinessTaxNumber { get; set; }
public string BillingEmail { get; set; }
public string BillingPhone { get; set; }
public ProviderStatusType Status { get; set; }
public bool UseEvents { get; set; }
public ProviderType Type { get; set; }
public bool Enabled { get; set; } = true;
public DateTime CreationDate { get; internal set; } = DateTime.UtcNow;
public DateTime RevisionDate { get; internal set; } = DateTime.UtcNow;
public void SetNewId()
{
if (Id == default)
{
Id = CoreHelpers.GenerateComb();
}
}
}

View File

@ -0,0 +1,23 @@
using Bit.Core.Entities;
using Bit.Core.Utilities;
namespace Bit.Core.AdminConsole.Entities.Provider;
public class ProviderOrganization : ITableObject<Guid>
{
public Guid Id { get; set; }
public Guid ProviderId { get; set; }
public Guid OrganizationId { get; set; }
public string Key { get; set; }
public string Settings { get; set; }
public DateTime CreationDate { get; internal set; } = DateTime.UtcNow;
public DateTime RevisionDate { get; internal set; } = DateTime.UtcNow;
public void SetNewId()
{
if (Id == default)
{
Id = CoreHelpers.GenerateComb();
}
}
}

View File

@ -0,0 +1,27 @@
using Bit.Core.AdminConsole.Enums.Provider;
using Bit.Core.Entities;
using Bit.Core.Utilities;
namespace Bit.Core.AdminConsole.Entities.Provider;
public class ProviderUser : ITableObject<Guid>
{
public Guid Id { get; set; }
public Guid ProviderId { get; set; }
public Guid? UserId { get; set; }
public string Email { get; set; }
public string Key { get; set; }
public ProviderUserStatusType Status { get; set; }
public ProviderUserType Type { get; set; }
public string Permissions { get; set; }
public DateTime CreationDate { get; set; } = DateTime.UtcNow;
public DateTime RevisionDate { get; set; } = DateTime.UtcNow;
public void SetNewId()
{
if (Id == default)
{
Id = CoreHelpers.GenerateComb();
}
}
}

View File

@ -0,0 +1,7 @@
namespace Bit.Core.AdminConsole.Enums.Provider;
public enum ProviderStatusType : byte
{
Pending = 0,
Created = 1,
}

View File

@ -0,0 +1,11 @@
using System.ComponentModel.DataAnnotations;
namespace Bit.Core.AdminConsole.Enums.Provider;
public enum ProviderType : byte
{
[Display(ShortName = "MSP", Name = "Managed Service Provider", Description = "Access to clients organization")]
Msp = 0,
[Display(ShortName = "Reseller", Name = "Reseller", Description = "Access to clients billing")]
Reseller = 1,
}

View File

@ -0,0 +1,8 @@
namespace Bit.Core.AdminConsole.Enums.Provider;
public enum ProviderUserStatusType : byte
{
Invited = 0,
Accepted = 1,
Confirmed = 2,
}

View File

@ -0,0 +1,7 @@
namespace Bit.Core.AdminConsole.Enums.Provider;
public enum ProviderUserType : byte
{
ProviderAdmin = 0,
ServiceUser = 1,
}

View File

@ -0,0 +1,35 @@
using Bit.Core.AdminConsole.Enums.Provider;
namespace Bit.Core.AdminConsole.Models.Business.Provider;
public class ProviderUserInvite<T>
{
public IEnumerable<T> UserIdentifiers { get; set; }
public ProviderUserType Type { get; set; }
public Guid InvitingUserId { get; set; }
public Guid ProviderId { get; set; }
}
public static class ProviderUserInviteFactory
{
public static ProviderUserInvite<string> CreateInitialInvite(IEnumerable<string> inviteeEmails, ProviderUserType type, Guid invitingUserId, Guid providerId)
{
return new ProviderUserInvite<string>
{
UserIdentifiers = inviteeEmails,
Type = type,
InvitingUserId = invitingUserId,
ProviderId = providerId
};
}
public static ProviderUserInvite<Guid> CreateReinvite(IEnumerable<Guid> inviteeUserIds, Guid invitingUserId, Guid providerId)
{
return new ProviderUserInvite<Guid>
{
UserIdentifiers = inviteeUserIds,
InvitingUserId = invitingUserId,
ProviderId = providerId
};
}
}

View File

@ -0,0 +1,17 @@
namespace Bit.Core.AdminConsole.Models.Data.Provider;
public class ProviderAbility
{
public ProviderAbility() { }
public ProviderAbility(Entities.Provider.Provider provider)
{
Id = provider.Id;
UseEvents = provider.UseEvents;
Enabled = provider.Enabled;
}
public Guid Id { get; set; }
public bool UseEvents { get; set; }
public bool Enabled { get; set; }
}

View File

@ -0,0 +1,19 @@
using Bit.Core.Enums;
namespace Bit.Core.AdminConsole.Models.Data.Provider;
public class ProviderOrganizationOrganizationDetails
{
public Guid Id { get; set; }
public Guid ProviderId { get; set; }
public Guid OrganizationId { get; set; }
public string OrganizationName { get; set; }
public string Key { get; set; }
public string Settings { get; set; }
public DateTime CreationDate { get; set; }
public DateTime RevisionDate { get; set; }
public int UserCount { get; set; }
public int? Seats { get; set; }
public string Plan { get; set; }
public OrganizationStatusType Status { get; set; }
}

View File

@ -0,0 +1,12 @@
using Bit.Core.AdminConsole.Enums.Provider;
namespace Bit.Core.AdminConsole.Models.Data.Provider;
public class ProviderOrganizationProviderDetails
{
public Guid Id { get; set; }
public Guid ProviderId { get; set; }
public Guid OrganizationId { get; set; }
public string ProviderName { get; set; }
public ProviderType ProviderType { get; set; }
}

View File

@ -0,0 +1,38 @@
using Bit.Core.AdminConsole.Enums.Provider;
namespace Bit.Core.AdminConsole.Models.Data.Provider;
public class ProviderUserOrganizationDetails
{
public Guid OrganizationId { get; set; }
public Guid? UserId { get; set; }
public string Name { get; set; }
public bool UsePolicies { get; set; }
public bool UseSso { get; set; }
public bool UseKeyConnector { get; set; }
public bool UseScim { get; set; }
public bool UseGroups { get; set; }
public bool UseDirectory { get; set; }
public bool UseEvents { get; set; }
public bool UseTotp { get; set; }
public bool Use2fa { get; set; }
public bool UseApi { get; set; }
public bool UseResetPassword { get; set; }
public bool SelfHost { get; set; }
public bool UsersGetPremium { get; set; }
public bool UseCustomPermissions { get; set; }
public int? Seats { get; set; }
public short? MaxCollections { get; set; }
public short? MaxStorageGb { get; set; }
public string Key { get; set; }
public ProviderUserStatusType Status { get; set; }
public ProviderUserType Type { get; set; }
public bool Enabled { get; set; }
public string Identifier { get; set; }
public string PublicKey { get; set; }
public string PrivateKey { get; set; }
public Guid? ProviderId { get; set; }
public Guid? ProviderUserId { get; set; }
public string ProviderName { get; set; }
public Core.Enums.PlanType PlanType { get; set; }
}

View File

@ -0,0 +1,17 @@
using Bit.Core.AdminConsole.Enums.Provider;
namespace Bit.Core.AdminConsole.Models.Data.Provider;
public class ProviderUserProviderDetails
{
public Guid ProviderId { get; set; }
public Guid? UserId { get; set; }
public string Name { get; set; }
public string Key { get; set; }
public ProviderUserStatusType Status { get; set; }
public ProviderUserType Type { get; set; }
public bool Enabled { get; set; }
public string Permissions { get; set; }
public bool UseEvents { get; set; }
public ProviderStatusType ProviderStatus { get; set; }
}

View File

@ -0,0 +1,8 @@
namespace Bit.Core.AdminConsole.Models.Data.Provider;
public class ProviderUserPublicKey
{
public Guid Id { get; set; }
public Guid UserId { get; set; }
public string PublicKey { get; set; }
}

View File

@ -0,0 +1,15 @@
using Bit.Core.AdminConsole.Enums.Provider;
namespace Bit.Core.AdminConsole.Models.Data.Provider;
public class ProviderUserUserDetails
{
public Guid Id { get; set; }
public Guid ProviderId { get; set; }
public Guid? UserId { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public ProviderUserStatusType Status { get; set; }
public ProviderUserType Type { get; set; }
public string Permissions { get; set; }
}

View File

@ -0,0 +1,9 @@
using Bit.Core.AdminConsole.Entities.Provider;
namespace Bit.Core.AdminConsole.Providers.Interfaces;
public interface ICreateProviderCommand
{
Task CreateMspAsync(Provider provider, string ownerEmail);
Task CreateResellerAsync(Provider provider);
}

View File

@ -0,0 +1,14 @@
using Bit.Core.AdminConsole.Entities.Provider;
using Bit.Core.AdminConsole.Models.Data.Provider;
using Bit.Core.Repositories;
namespace Bit.Core.AdminConsole.Repositories;
public interface IProviderOrganizationRepository : IRepository<ProviderOrganization, Guid>
{
Task<ICollection<ProviderOrganization>> CreateManyAsync(IEnumerable<ProviderOrganization> providerOrganizations);
Task<ICollection<ProviderOrganizationOrganizationDetails>> GetManyDetailsByProviderAsync(Guid providerId);
Task<ProviderOrganization> GetByOrganizationId(Guid organizationId);
Task<IEnumerable<ProviderOrganizationProviderDetails>> GetManyByUserAsync(Guid userId);
Task<int> GetCountByOrganizationIdsAsync(IEnumerable<Guid> organizationIds);
}

View File

@ -0,0 +1,12 @@
using Bit.Core.AdminConsole.Entities.Provider;
using Bit.Core.AdminConsole.Models.Data.Provider;
using Bit.Core.Repositories;
namespace Bit.Core.AdminConsole.Repositories;
public interface IProviderRepository : IRepository<Provider, Guid>
{
Task<Provider> GetByOrganizationIdAsync(Guid organizationId);
Task<ICollection<Provider>> SearchAsync(string name, string userEmail, int skip, int take);
Task<ICollection<ProviderAbility>> GetManyAbilitiesAsync();
}

View File

@ -0,0 +1,23 @@
using Bit.Core.AdminConsole.Entities.Provider;
using Bit.Core.AdminConsole.Enums.Provider;
using Bit.Core.AdminConsole.Models.Data.Provider;
using Bit.Core.Repositories;
namespace Bit.Core.AdminConsole.Repositories;
public interface IProviderUserRepository : IRepository<ProviderUser, Guid>
{
Task<int> GetCountByProviderAsync(Guid providerId, string email, bool onlyRegisteredUsers);
Task<ICollection<ProviderUser>> GetManyAsync(IEnumerable<Guid> ids);
Task<ICollection<ProviderUser>> GetManyByUserAsync(Guid userId);
Task<ProviderUser> GetByProviderUserAsync(Guid providerId, Guid userId);
Task<ICollection<ProviderUser>> GetManyByProviderAsync(Guid providerId, ProviderUserType? type = null);
Task<ICollection<ProviderUserUserDetails>> GetManyDetailsByProviderAsync(Guid providerId, ProviderUserStatusType? status = null);
Task<ICollection<ProviderUserProviderDetails>> GetManyDetailsByUserAsync(Guid userId,
ProviderUserStatusType? status = null);
Task<IEnumerable<ProviderUserOrganizationDetails>> GetManyOrganizationDetailsByUserAsync(Guid userId, ProviderUserStatusType? status = null);
Task DeleteManyAsync(IEnumerable<Guid> userIds);
Task<IEnumerable<ProviderUserPublicKey>> GetManyPublicKeysByProviderUserAsync(Guid providerId, IEnumerable<Guid> Ids);
Task<int> GetCountByOnlyOwnerAsync(Guid userId);
Task<ICollection<ProviderUser>> GetManyByOrganizationAsync(Guid organizationId, ProviderUserStatusType? status = null);
}

View File

@ -0,0 +1,31 @@
using Bit.Core.AdminConsole.Entities.Provider;
using Bit.Core.AdminConsole.Models.Business.Provider;
using Bit.Core.Entities;
using Bit.Core.Models.Business;
namespace Bit.Core.AdminConsole.Services;
public interface IProviderService
{
Task<Provider> CompleteSetupAsync(Provider provider, Guid ownerUserId, string token, string key);
Task UpdateAsync(Provider provider, bool updateBilling = false);
Task<List<ProviderUser>> InviteUserAsync(ProviderUserInvite<string> invite);
Task<List<Tuple<ProviderUser, string>>> ResendInvitesAsync(ProviderUserInvite<Guid> invite);
Task<ProviderUser> AcceptUserAsync(Guid providerUserId, User user, string token);
Task<List<Tuple<ProviderUser, string>>> ConfirmUsersAsync(Guid providerId, Dictionary<Guid, string> keys, Guid confirmingUserId);
Task SaveUserAsync(ProviderUser user, Guid savingUserId);
Task<List<Tuple<ProviderUser, string>>> DeleteUsersAsync(Guid providerId, IEnumerable<Guid> providerUserIds,
Guid deletingUserId);
Task AddOrganization(Guid providerId, Guid organizationId, string key);
Task AddOrganizationsToReseller(Guid providerId, IEnumerable<Guid> organizationIds);
Task<ProviderOrganization> CreateOrganizationAsync(Guid providerId, OrganizationSignup organizationSignup,
string clientOwnerEmail, User user);
Task RemoveOrganizationAsync(Guid providerId, Guid providerOrganizationId, Guid removingUserId);
Task LogProviderAccessToOrganizationAsync(Guid organizationId);
Task ResendProviderSetupInviteEmailAsync(Guid providerId, Guid ownerId);
Task SendProviderSetupInviteEmailAsync(Provider provider, string ownerEmail);
}

View File

@ -0,0 +1,38 @@
using Bit.Core.AdminConsole.Entities.Provider;
using Bit.Core.AdminConsole.Models.Business.Provider;
using Bit.Core.Entities;
using Bit.Core.Models.Business;
namespace Bit.Core.AdminConsole.Services.NoopImplementations;
public class NoopProviderService : IProviderService
{
public Task<Provider> CompleteSetupAsync(Provider provider, Guid ownerUserId, string token, string key) => throw new NotImplementedException();
public Task UpdateAsync(Provider provider, bool updateBilling = false) => throw new NotImplementedException();
public Task<List<ProviderUser>> InviteUserAsync(ProviderUserInvite<string> invite) => throw new NotImplementedException();
public Task<List<Tuple<ProviderUser, string>>> ResendInvitesAsync(ProviderUserInvite<Guid> invite) => throw new NotImplementedException();
public Task<ProviderUser> AcceptUserAsync(Guid providerUserId, User user, string token) => throw new NotImplementedException();
public Task<List<Tuple<ProviderUser, string>>> ConfirmUsersAsync(Guid providerId, Dictionary<Guid, string> keys, Guid confirmingUserId) => throw new NotImplementedException();
public Task SaveUserAsync(ProviderUser user, Guid savingUserId) => throw new NotImplementedException();
public Task<List<Tuple<ProviderUser, string>>> DeleteUsersAsync(Guid providerId, IEnumerable<Guid> providerUserIds, Guid deletingUserId) => throw new NotImplementedException();
public Task AddOrganization(Guid providerId, Guid organizationId, string key) => throw new NotImplementedException();
public Task AddOrganizationsToReseller(Guid providerId, IEnumerable<Guid> organizationIds) => throw new NotImplementedException();
public Task<ProviderOrganization> CreateOrganizationAsync(Guid providerId, OrganizationSignup organizationSignup, string clientOwnerEmail, User user) => throw new NotImplementedException();
public Task RemoveOrganizationAsync(Guid providerId, Guid providerOrganizationId, Guid removingUserId) => throw new NotImplementedException();
public Task LogProviderAccessToOrganizationAsync(Guid organizationId) => throw new NotImplementedException();
public Task ResendProviderSetupInviteEmailAsync(Guid providerId, Guid userId) => throw new NotImplementedException();
public Task SendProviderSetupInviteEmailAsync(Provider provider, string ownerEmail) => throw new NotImplementedException();
}