mirror of
https://github.com/bitwarden/server.git
synced 2025-07-02 00:22:50 -05:00
Merge branch 'feature/billing-obfuscation' into AC-432-add-existing-organization-flow-server-admin-portal-database
This commit is contained in:
@ -4,7 +4,7 @@ namespace Bit.Api.Models.Request.Accounts;
|
|||||||
|
|
||||||
public class ImportCiphersRequestModel
|
public class ImportCiphersRequestModel
|
||||||
{
|
{
|
||||||
public FolderRequestModel[] Folders { get; set; }
|
public FolderWithIdRequestModel[] Folders { get; set; }
|
||||||
public CipherRequestModel[] Ciphers { get; set; }
|
public CipherRequestModel[] Ciphers { get; set; }
|
||||||
public KeyValuePair<int, int>[] FolderRelationships { get; set; }
|
public KeyValuePair<int, int>[] FolderRelationships { get; set; }
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@ public class CollectionRequestModel
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection ToCollection(Collection existingCollection)
|
public virtual Collection ToCollection(Collection existingCollection)
|
||||||
{
|
{
|
||||||
existingCollection.Name = Name;
|
existingCollection.Name = Name;
|
||||||
existingCollection.ExternalId = ExternalId;
|
existingCollection.ExternalId = ExternalId;
|
||||||
@ -37,3 +37,14 @@ public class CollectionBulkDeleteRequestModel
|
|||||||
public IEnumerable<string> Ids { get; set; }
|
public IEnumerable<string> Ids { get; set; }
|
||||||
public string OrganizationId { get; set; }
|
public string OrganizationId { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class CollectionWithIdRequestModel : CollectionRequestModel
|
||||||
|
{
|
||||||
|
public Guid? Id { get; set; }
|
||||||
|
|
||||||
|
public override Collection ToCollection(Collection existingCollection)
|
||||||
|
{
|
||||||
|
existingCollection.Id = Id ?? Guid.Empty;
|
||||||
|
return base.ToCollection(existingCollection);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -4,7 +4,7 @@ namespace Bit.Api.Models.Request.Organizations;
|
|||||||
|
|
||||||
public class ImportOrganizationCiphersRequestModel
|
public class ImportOrganizationCiphersRequestModel
|
||||||
{
|
{
|
||||||
public CollectionRequestModel[] Collections { get; set; }
|
public CollectionWithIdRequestModel[] Collections { get; set; }
|
||||||
public CipherRequestModel[] Ciphers { get; set; }
|
public CipherRequestModel[] Ciphers { get; set; }
|
||||||
public KeyValuePair<int, int>[] CollectionRelationships { get; set; }
|
public KeyValuePair<int, int>[] CollectionRelationships { get; set; }
|
||||||
}
|
}
|
||||||
|
@ -16,13 +16,11 @@ public class OrganizationDomainSsoDetailsResponseModel : ResponseModel
|
|||||||
SsoAvailable = data.SsoAvailable;
|
SsoAvailable = data.SsoAvailable;
|
||||||
DomainName = data.DomainName;
|
DomainName = data.DomainName;
|
||||||
OrganizationIdentifier = data.OrganizationIdentifier;
|
OrganizationIdentifier = data.OrganizationIdentifier;
|
||||||
SsoRequired = data.SsoRequired;
|
|
||||||
VerifiedDate = data.VerifiedDate;
|
VerifiedDate = data.VerifiedDate;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool SsoAvailable { get; private set; }
|
public bool SsoAvailable { get; private set; }
|
||||||
public string DomainName { get; private set; }
|
public string DomainName { get; private set; }
|
||||||
public string OrganizationIdentifier { get; private set; }
|
public string OrganizationIdentifier { get; private set; }
|
||||||
public bool SsoRequired { get; private set; }
|
|
||||||
public DateTime? VerifiedDate { get; private set; }
|
public DateTime? VerifiedDate { get; private set; }
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,7 @@ public class FolderRequestModel
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public Folder ToFolder(Folder existingFolder)
|
public virtual Folder ToFolder(Folder existingFolder)
|
||||||
{
|
{
|
||||||
existingFolder.Name = Name;
|
existingFolder.Name = Name;
|
||||||
return existingFolder;
|
return existingFolder;
|
||||||
@ -28,5 +28,11 @@ public class FolderRequestModel
|
|||||||
|
|
||||||
public class FolderWithIdRequestModel : FolderRequestModel
|
public class FolderWithIdRequestModel : FolderRequestModel
|
||||||
{
|
{
|
||||||
public Guid Id { get; set; }
|
public Guid? Id { get; set; }
|
||||||
|
|
||||||
|
public override Folder ToFolder(Folder existingFolder)
|
||||||
|
{
|
||||||
|
existingFolder.Id = Id ?? Guid.Empty;
|
||||||
|
return base.ToFolder(existingFolder);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,4 @@
|
|||||||
using Bit.Core.Enums;
|
namespace Bit.Core.Models.Data.Organizations;
|
||||||
|
|
||||||
namespace Bit.Core.Models.Data.Organizations;
|
|
||||||
|
|
||||||
public class OrganizationDomainSsoDetailsData
|
public class OrganizationDomainSsoDetailsData
|
||||||
{
|
{
|
||||||
@ -9,8 +7,6 @@ public class OrganizationDomainSsoDetailsData
|
|||||||
public string DomainName { get; set; }
|
public string DomainName { get; set; }
|
||||||
public bool SsoAvailable { get; set; }
|
public bool SsoAvailable { get; set; }
|
||||||
public string OrganizationIdentifier { get; set; }
|
public string OrganizationIdentifier { get; set; }
|
||||||
public bool SsoRequired { get; set; }
|
|
||||||
public PolicyType? PolicyType { get; set; }
|
|
||||||
public DateTime? VerifiedDate { get; set; }
|
public DateTime? VerifiedDate { get; set; }
|
||||||
public bool OrganizationEnabled { get; set; }
|
public bool OrganizationEnabled { get; set; }
|
||||||
}
|
}
|
||||||
|
@ -648,10 +648,18 @@ public class CipherService : ICipherService
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init. ids for folders
|
var userfoldersIds = (await _folderRepository.GetManyByUserIdAsync(userId ?? Guid.Empty)).Select(f => f.Id).ToList();
|
||||||
|
|
||||||
|
//Assign id to the ones that don't exist in DB
|
||||||
|
//Need to keep the list order to create the relationships
|
||||||
|
List<Folder> newFolders = new List<Folder>();
|
||||||
foreach (var folder in folders)
|
foreach (var folder in folders)
|
||||||
{
|
{
|
||||||
folder.SetNewId();
|
if (!userfoldersIds.Contains(folder.Id))
|
||||||
|
{
|
||||||
|
folder.SetNewId();
|
||||||
|
newFolders.Add(folder);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the folder associations based on the newly created folder ids
|
// Create the folder associations based on the newly created folder ids
|
||||||
@ -670,7 +678,7 @@ public class CipherService : ICipherService
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create it all
|
// Create it all
|
||||||
await _cipherRepository.CreateAsync(ciphers, folders);
|
await _cipherRepository.CreateAsync(ciphers, newFolders);
|
||||||
|
|
||||||
// push
|
// push
|
||||||
if (userId.HasValue)
|
if (userId.HasValue)
|
||||||
@ -705,10 +713,19 @@ public class CipherService : ICipherService
|
|||||||
cipher.SetNewId();
|
cipher.SetNewId();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init. ids for collections
|
var userCollectionsIds = (await _collectionRepository.GetManyByOrganizationIdAsync(org.Id)).Select(c => c.Id).ToList();
|
||||||
|
|
||||||
|
//Assign id to the ones that don't exist in DB
|
||||||
|
//Need to keep the list order to create the relationships
|
||||||
|
List<Collection> newCollections = new List<Collection>();
|
||||||
|
|
||||||
foreach (var collection in collections)
|
foreach (var collection in collections)
|
||||||
{
|
{
|
||||||
collection.SetNewId();
|
if (!userCollectionsIds.Contains(collection.Id))
|
||||||
|
{
|
||||||
|
collection.SetNewId();
|
||||||
|
newCollections.Add(collection);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create associations based on the newly assigned ids
|
// Create associations based on the newly assigned ids
|
||||||
@ -731,7 +748,7 @@ public class CipherService : ICipherService
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create it all
|
// Create it all
|
||||||
await _cipherRepository.CreateAsync(ciphers, collections, collectionCiphers);
|
await _cipherRepository.CreateAsync(ciphers, newCollections, collectionCiphers);
|
||||||
|
|
||||||
// push
|
// push
|
||||||
await _pushService.PushSyncVaultAsync(importingUserId);
|
await _pushService.PushSyncVaultAsync(importingUserId);
|
||||||
|
@ -616,15 +616,15 @@ public class CipherRepository : Repository<Cipher, Guid>, ICipherRepository
|
|||||||
var dataTable = BuildCollectionsTable(bulkCopy, collections);
|
var dataTable = BuildCollectionsTable(bulkCopy, collections);
|
||||||
bulkCopy.WriteToServer(dataTable);
|
bulkCopy.WriteToServer(dataTable);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (collectionCiphers.Any())
|
if (collectionCiphers.Any())
|
||||||
|
{
|
||||||
|
using (var bulkCopy = new SqlBulkCopy(connection, SqlBulkCopyOptions.KeepIdentity, transaction))
|
||||||
{
|
{
|
||||||
using (var bulkCopy = new SqlBulkCopy(connection, SqlBulkCopyOptions.KeepIdentity, transaction))
|
bulkCopy.DestinationTableName = "[dbo].[CollectionCipher]";
|
||||||
{
|
var dataTable = BuildCollectionCiphersTable(bulkCopy, collectionCiphers);
|
||||||
bulkCopy.DestinationTableName = "[dbo].[CollectionCipher]";
|
bulkCopy.WriteToServer(dataTable);
|
||||||
var dataTable = BuildCollectionCiphersTable(bulkCopy, collectionCiphers);
|
|
||||||
bulkCopy.WriteToServer(dataTable);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
using System.Net.Mail;
|
using System.Net.Mail;
|
||||||
using AutoMapper;
|
using AutoMapper;
|
||||||
using Bit.Core.Enums;
|
|
||||||
using Bit.Core.Models.Data.Organizations;
|
using Bit.Core.Models.Data.Organizations;
|
||||||
using Bit.Core.Repositories;
|
using Bit.Core.Repositories;
|
||||||
using Bit.Infrastructure.EntityFramework.Models;
|
using Bit.Infrastructure.EntityFramework.Models;
|
||||||
@ -78,19 +77,14 @@ public class OrganizationDomainRepository : Repository<Core.Entities.Organizatio
|
|||||||
from od in o.Domains
|
from od in o.Domains
|
||||||
join s in dbContext.SsoConfigs on o.Id equals s.OrganizationId into sJoin
|
join s in dbContext.SsoConfigs on o.Id equals s.OrganizationId into sJoin
|
||||||
from s in sJoin.DefaultIfEmpty()
|
from s in sJoin.DefaultIfEmpty()
|
||||||
join p in dbContext.Policies.Where(p => p.Type == PolicyType.RequireSso) on o.Id
|
|
||||||
equals p.OrganizationId into pJoin
|
|
||||||
from p in pJoin.DefaultIfEmpty()
|
|
||||||
where od.DomainName == domainName && o.Enabled
|
where od.DomainName == domainName && o.Enabled
|
||||||
select new OrganizationDomainSsoDetailsData
|
select new OrganizationDomainSsoDetailsData
|
||||||
{
|
{
|
||||||
OrganizationId = o.Id,
|
OrganizationId = o.Id,
|
||||||
OrganizationName = o.Name,
|
OrganizationName = o.Name,
|
||||||
SsoAvailable = o.SsoConfigs.Any(sc => sc.Enabled),
|
SsoAvailable = o.SsoConfigs.Any(sc => sc.Enabled),
|
||||||
SsoRequired = p != null && p.Enabled,
|
|
||||||
OrganizationIdentifier = o.Identifier,
|
OrganizationIdentifier = o.Identifier,
|
||||||
VerifiedDate = od.VerifiedDate,
|
VerifiedDate = od.VerifiedDate,
|
||||||
PolicyType = p.Type,
|
|
||||||
DomainName = od.DomainName
|
DomainName = od.DomainName
|
||||||
})
|
})
|
||||||
.AsNoTracking()
|
.AsNoTracking()
|
||||||
|
@ -168,16 +168,17 @@ public class CipherRepository : Repository<Core.Vault.Entities.Cipher, Cipher, G
|
|||||||
var dbContext = GetDatabaseContext(scope);
|
var dbContext = GetDatabaseContext(scope);
|
||||||
var cipherEntities = Mapper.Map<List<Cipher>>(ciphers);
|
var cipherEntities = Mapper.Map<List<Cipher>>(ciphers);
|
||||||
await dbContext.BulkCopyAsync(base.DefaultBulkCopyOptions, cipherEntities);
|
await dbContext.BulkCopyAsync(base.DefaultBulkCopyOptions, cipherEntities);
|
||||||
|
|
||||||
if (collections.Any())
|
if (collections.Any())
|
||||||
{
|
{
|
||||||
var collectionEntities = Mapper.Map<List<Collection>>(collections);
|
var collectionEntities = Mapper.Map<List<Collection>>(collections);
|
||||||
await dbContext.BulkCopyAsync(base.DefaultBulkCopyOptions, collectionEntities);
|
await dbContext.BulkCopyAsync(base.DefaultBulkCopyOptions, collectionEntities);
|
||||||
|
}
|
||||||
|
|
||||||
if (collectionCiphers.Any())
|
if (collectionCiphers.Any())
|
||||||
{
|
{
|
||||||
var collectionCipherEntities = Mapper.Map<List<CollectionCipher>>(collectionCiphers);
|
var collectionCipherEntities = Mapper.Map<List<CollectionCipher>>(collectionCiphers);
|
||||||
await dbContext.BulkCopyAsync(base.DefaultBulkCopyOptions, collectionCipherEntities);
|
await dbContext.BulkCopyAsync(base.DefaultBulkCopyOptions, collectionCipherEntities);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
await dbContext.UserBumpAccountRevisionDateByOrganizationIdAsync(ciphers.First().OrganizationId.Value);
|
await dbContext.UserBumpAccountRevisionDateByOrganizationIdAsync(ciphers.First().OrganizationId.Value);
|
||||||
await dbContext.SaveChangesAsync();
|
await dbContext.SaveChangesAsync();
|
||||||
|
@ -12,20 +12,15 @@ BEGIN
|
|||||||
O.Id AS OrganizationId,
|
O.Id AS OrganizationId,
|
||||||
O.[Name] AS OrganizationName,
|
O.[Name] AS OrganizationName,
|
||||||
S.Enabled AS SsoAvailable,
|
S.Enabled AS SsoAvailable,
|
||||||
P.Enabled AS SsoRequired,
|
|
||||||
O.Identifier AS OrganizationIdentifier,
|
O.Identifier AS OrganizationIdentifier,
|
||||||
OD.VerifiedDate,
|
OD.VerifiedDate,
|
||||||
P.[Type] AS PolicyType,
|
|
||||||
OD.DomainName
|
OD.DomainName
|
||||||
FROM
|
FROM
|
||||||
[dbo].[OrganizationView] O
|
[dbo].[OrganizationView] O
|
||||||
INNER JOIN [dbo].[OrganizationDomainView] OD
|
INNER JOIN [dbo].[OrganizationDomainView] OD
|
||||||
ON O.Id = OD.OrganizationId
|
ON O.Id = OD.OrganizationId
|
||||||
LEFT JOIN [dbo].[PolicyView] P
|
|
||||||
ON O.Id = P.OrganizationId
|
|
||||||
LEFT JOIN [dbo].[Ssoconfig] S
|
LEFT JOIN [dbo].[Ssoconfig] S
|
||||||
ON O.Id = S.OrganizationId
|
ON O.Id = S.OrganizationId
|
||||||
WHERE OD.DomainName = @Domain
|
WHERE OD.DomainName = @Domain
|
||||||
AND O.Enabled = 1
|
AND O.Enabled = 1
|
||||||
AND (P.Id is NULL OR (P.Id IS NOT NULL AND P.[Type] = 4)) -- SSO Type
|
|
||||||
END
|
END
|
@ -0,0 +1,26 @@
|
|||||||
|
CREATE OR ALTER PROCEDURE [dbo].[OrganizationDomainSsoDetails_ReadByEmail]
|
||||||
|
@Email NVARCHAR(256)
|
||||||
|
AS
|
||||||
|
BEGIN
|
||||||
|
SET NOCOUNT ON
|
||||||
|
|
||||||
|
DECLARE @Domain NVARCHAR(256)
|
||||||
|
|
||||||
|
SELECT @Domain = SUBSTRING(@Email, CHARINDEX( '@', @Email) + 1, LEN(@Email))
|
||||||
|
|
||||||
|
SELECT
|
||||||
|
O.Id AS OrganizationId,
|
||||||
|
O.[Name] AS OrganizationName,
|
||||||
|
S.Enabled AS SsoAvailable,
|
||||||
|
O.Identifier AS OrganizationIdentifier,
|
||||||
|
OD.VerifiedDate,
|
||||||
|
OD.DomainName
|
||||||
|
FROM
|
||||||
|
[dbo].[OrganizationView] O
|
||||||
|
INNER JOIN [dbo].[OrganizationDomainView] OD
|
||||||
|
ON O.Id = OD.OrganizationId
|
||||||
|
LEFT JOIN [dbo].[Ssoconfig] S
|
||||||
|
ON O.Id = S.OrganizationId
|
||||||
|
WHERE OD.DomainName = @Domain
|
||||||
|
AND O.Enabled = 1
|
||||||
|
END
|
Reference in New Issue
Block a user