1
0
mirror of https://github.com/bitwarden/server.git synced 2025-05-07 12:42:24 -05:00

collection groups management

This commit is contained in:
Kyle Spearrin 2017-05-11 12:22:14 -04:00
parent 2b8db4d1ed
commit d7f9977382
9 changed files with 38 additions and 27 deletions

View File

@ -8,6 +8,7 @@ using Bit.Core.Models.Api;
using Bit.Core.Exceptions; using Bit.Core.Exceptions;
using Bit.Core.Services; using Bit.Core.Services;
using Bit.Core; using Bit.Core;
using Bit.Core.Models.Data;
namespace Bit.Api.Controllers namespace Bit.Api.Controllers
{ {
@ -91,7 +92,7 @@ namespace Bit.Api.Controllers
} }
var collection = model.ToCollection(orgIdGuid); var collection = model.ToCollection(orgIdGuid);
await _collectionService.SaveAsync(collection, model.GroupIds?.Select(g => new Guid(g))); await _collectionService.SaveAsync(collection, model.Groups?.Select(g => g.ToSelectionReadOnly()));
return new CollectionResponseModel(collection); return new CollectionResponseModel(collection);
} }
@ -105,7 +106,8 @@ namespace Bit.Api.Controllers
throw new NotFoundException(); throw new NotFoundException();
} }
await _collectionService.SaveAsync(model.ToCollection(collection), model.GroupIds?.Select(g => new Guid(g))); await _collectionService.SaveAsync(model.ToCollection(collection),
model.Groups?.Select(g => g.ToSelectionReadOnly()));
return new CollectionResponseModel(collection); return new CollectionResponseModel(collection);
} }

View File

@ -13,7 +13,7 @@ namespace Bit.Core.Models.Api
[EncryptedString] [EncryptedString]
[StringLength(300)] [StringLength(300)]
public string Name { get; set; } public string Name { get; set; }
public IEnumerable<string> GroupIds { get; set; } public IEnumerable<SelectionReadOnlyRequestModel> Groups { get; set; }
public Collection ToCollection(Guid orgId) public Collection ToCollection(Guid orgId)
{ {

View File

@ -1,6 +1,8 @@
using System; using System;
using Bit.Core.Models.Table; using Bit.Core.Models.Table;
using System.Collections.Generic; using System.Collections.Generic;
using Bit.Core.Models.Data;
using System.Linq;
namespace Bit.Core.Models.Api namespace Bit.Core.Models.Api
{ {
@ -26,12 +28,12 @@ namespace Bit.Core.Models.Api
public class CollectionDetailsResponseModel : CollectionResponseModel public class CollectionDetailsResponseModel : CollectionResponseModel
{ {
public CollectionDetailsResponseModel(Collection collection, IEnumerable<Guid> groupIds) public CollectionDetailsResponseModel(Collection collection, IEnumerable<SelectionReadOnly> groups)
: base(collection, "collectionDetails") : base(collection, "collectionDetails")
{ {
GroupIds = groupIds; Groups = groups.Select(g => new SelectionReadOnlyResponseModel(g));
} }
public IEnumerable<Guid> GroupIds { get; set; } public IEnumerable<SelectionReadOnlyResponseModel> Groups { get; set; }
} }
} }

View File

@ -2,17 +2,18 @@
using System.Threading.Tasks; using System.Threading.Tasks;
using Bit.Core.Models.Table; using Bit.Core.Models.Table;
using System.Collections.Generic; using System.Collections.Generic;
using Bit.Core.Models.Data;
namespace Bit.Core.Repositories namespace Bit.Core.Repositories
{ {
public interface ICollectionRepository : IRepository<Collection, Guid> public interface ICollectionRepository : IRepository<Collection, Guid>
{ {
Task<int> GetCountByOrganizationIdAsync(Guid organizationId); Task<int> GetCountByOrganizationIdAsync(Guid organizationId);
Task<Tuple<Collection, ICollection<Guid>>> GetByIdWithGroupsAsync(Guid id); Task<Tuple<Collection, ICollection<SelectionReadOnly>>> GetByIdWithGroupsAsync(Guid id);
Task<ICollection<Collection>> GetManyByOrganizationIdAsync(Guid organizationId); Task<ICollection<Collection>> GetManyByOrganizationIdAsync(Guid organizationId);
Task<ICollection<Collection>> GetManyByUserIdAsync(Guid userId); Task<ICollection<Collection>> GetManyByUserIdAsync(Guid userId);
Task CreateAsync(Collection obj, IEnumerable<Guid> groupIds); Task CreateAsync(Collection obj, IEnumerable<SelectionReadOnly> groups);
Task ReplaceAsync(Collection obj, IEnumerable<Guid> groupIds); Task ReplaceAsync(Collection obj, IEnumerable<SelectionReadOnly> groups);
} }
} }

View File

@ -8,6 +8,7 @@ using Dapper;
using System.Linq; using System.Linq;
using Newtonsoft.Json; using Newtonsoft.Json;
using Bit.Core.Utilities; using Bit.Core.Utilities;
using Bit.Core.Models.Data;
namespace Bit.Core.Repositories.SqlServer namespace Bit.Core.Repositories.SqlServer
{ {
@ -34,7 +35,7 @@ namespace Bit.Core.Repositories.SqlServer
} }
} }
public async Task<Tuple<Collection, ICollection<Guid>>> GetByIdWithGroupsAsync(Guid id) public async Task<Tuple<Collection, ICollection<SelectionReadOnly>>> GetByIdWithGroupsAsync(Guid id)
{ {
using(var connection = new SqlConnection(ConnectionString)) using(var connection = new SqlConnection(ConnectionString))
{ {
@ -44,9 +45,9 @@ namespace Bit.Core.Repositories.SqlServer
commandType: CommandType.StoredProcedure); commandType: CommandType.StoredProcedure);
var collection = await results.ReadFirstOrDefaultAsync<Collection>(); var collection = await results.ReadFirstOrDefaultAsync<Collection>();
var groupIds = (await results.ReadAsync<Guid>()).ToList(); var groups = (await results.ReadAsync<SelectionReadOnly>()).ToList();
return new Tuple<Collection, ICollection<Guid>>(collection, groupIds); return new Tuple<Collection, ICollection<SelectionReadOnly>>(collection, groups);
} }
} }
@ -80,11 +81,11 @@ namespace Bit.Core.Repositories.SqlServer
} }
} }
public async Task CreateAsync(Collection obj, IEnumerable<Guid> groupIds) public async Task CreateAsync(Collection obj, IEnumerable<SelectionReadOnly> groups)
{ {
obj.SetNewId(); obj.SetNewId();
var objWithGroups = JsonConvert.DeserializeObject<CollectionWithGroups>(JsonConvert.SerializeObject(obj)); var objWithGroups = JsonConvert.DeserializeObject<CollectionWithGroups>(JsonConvert.SerializeObject(obj));
objWithGroups.GroupIds = groupIds.ToGuidIdArrayTVP(); objWithGroups.Groups = groups.ToArrayTVP();
using(var connection = new SqlConnection(ConnectionString)) using(var connection = new SqlConnection(ConnectionString))
{ {
@ -95,10 +96,10 @@ namespace Bit.Core.Repositories.SqlServer
} }
} }
public async Task ReplaceAsync(Collection obj, IEnumerable<Guid> groupIds) public async Task ReplaceAsync(Collection obj, IEnumerable<SelectionReadOnly> groups)
{ {
var objWithGroups = JsonConvert.DeserializeObject<CollectionWithGroups>(JsonConvert.SerializeObject(obj)); var objWithGroups = JsonConvert.DeserializeObject<CollectionWithGroups>(JsonConvert.SerializeObject(obj));
objWithGroups.GroupIds = groupIds.ToGuidIdArrayTVP(); objWithGroups.Groups = groups.ToArrayTVP();
using(var connection = new SqlConnection(ConnectionString)) using(var connection = new SqlConnection(ConnectionString))
{ {
@ -111,7 +112,7 @@ namespace Bit.Core.Repositories.SqlServer
public class CollectionWithGroups : Collection public class CollectionWithGroups : Collection
{ {
public DataTable GroupIds { get; set; } public DataTable Groups { get; set; }
} }
} }
} }

View File

@ -2,11 +2,12 @@
using Bit.Core.Models.Table; using Bit.Core.Models.Table;
using System.Collections.Generic; using System.Collections.Generic;
using System; using System;
using Bit.Core.Models.Data;
namespace Bit.Core.Services namespace Bit.Core.Services
{ {
public interface ICollectionService public interface ICollectionService
{ {
Task SaveAsync(Collection collection, IEnumerable<Guid> groupIds = null); Task SaveAsync(Collection collection, IEnumerable<SelectionReadOnly> groups = null);
} }
} }

View File

@ -4,6 +4,7 @@ using Bit.Core.Exceptions;
using Bit.Core.Models.Table; using Bit.Core.Models.Table;
using Bit.Core.Repositories; using Bit.Core.Repositories;
using System.Collections.Generic; using System.Collections.Generic;
using Bit.Core.Models.Data;
namespace Bit.Core.Services namespace Bit.Core.Services
{ {
@ -32,7 +33,7 @@ namespace Bit.Core.Services
_mailService = mailService; _mailService = mailService;
} }
public async Task SaveAsync(Collection collection, IEnumerable<Guid> groupIds = null) public async Task SaveAsync(Collection collection, IEnumerable<SelectionReadOnly> groups = null)
{ {
var org = await _organizationRepository.GetByIdAsync(collection.OrganizationId); var org = await _organizationRepository.GetByIdAsync(collection.OrganizationId);
if(org == null) if(org == null)
@ -52,24 +53,24 @@ namespace Bit.Core.Services
} }
} }
if(groupIds == null || !org.UseGroups) if(groups == null || !org.UseGroups)
{ {
await _collectionRepository.CreateAsync(collection); await _collectionRepository.CreateAsync(collection);
} }
else else
{ {
await _collectionRepository.CreateAsync(collection, groupIds); await _collectionRepository.CreateAsync(collection, groups);
} }
} }
else else
{ {
if(groupIds == null || !org.UseGroups) if(groups == null || !org.UseGroups)
{ {
await _collectionRepository.ReplaceAsync(collection); await _collectionRepository.ReplaceAsync(collection);
} }
else else
{ {
await _collectionRepository.ReplaceAsync(collection, groupIds); await _collectionRepository.ReplaceAsync(collection, groups);
} }
} }
} }

View File

@ -7,7 +7,8 @@ BEGIN
EXEC [dbo].[Collection_ReadById] @Id EXEC [dbo].[Collection_ReadById] @Id
SELECT SELECT
[GroupId] [GroupId] [Id],
[ReadOnly]
FROM FROM
[dbo].[CollectionGroup] [dbo].[CollectionGroup]
WHERE WHERE

View File

@ -4,7 +4,7 @@
@Name VARCHAR(MAX), @Name VARCHAR(MAX),
@CreationDate DATETIME2(7), @CreationDate DATETIME2(7),
@RevisionDate DATETIME2(7), @RevisionDate DATETIME2(7),
@GroupIds AS [dbo].[GuidIdArray] READONLY @Groups AS [dbo].[SelectionReadOnlyArray] READONLY
AS AS
BEGIN BEGIN
SET NOCOUNT ON SET NOCOUNT ON
@ -22,7 +22,7 @@ BEGIN
MERGE MERGE
[dbo].[CollectionGroup] AS [Target] [dbo].[CollectionGroup] AS [Target]
USING USING
@GroupIds AS [Source] @Groups AS [Source]
ON ON
[Target].[CollectionId] = @Id [Target].[CollectionId] = @Id
AND [Target].[GroupId] = [Source].[Id] AND [Target].[GroupId] = [Source].[Id]
@ -32,8 +32,10 @@ BEGIN
( (
@Id, @Id,
[Source].[Id], [Source].[Id],
0 [Source].[ReadOnly]
) )
WHEN MATCHED AND [Target].[ReadOnly] != [Source].[ReadOnly] THEN
UPDATE SET [Target].[ReadOnly] = [Source].[ReadOnly]
WHEN NOT MATCHED BY SOURCE WHEN NOT MATCHED BY SOURCE
AND [Target].[CollectionId] = @Id THEN AND [Target].[CollectionId] = @Id THEN
DELETE DELETE