mirror of
https://github.com/bitwarden/server
synced 2026-01-02 16:43:25 +00:00
Merge branch 'main' into auth/pm-22975/client-version-validator
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
using System.Text.Json;
|
||||
using Bit.Core.AdminConsole.Entities;
|
||||
using Bit.Core.Entities;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Models.Data;
|
||||
using Bit.Core.Models.Data.Organizations.OrganizationUsers;
|
||||
|
||||
namespace Bit.Core.AdminConsole.Models.Data.EventIntegrations;
|
||||
|
||||
@@ -36,13 +36,18 @@ public class IntegrationTemplateContext(EventMessage eventMessage)
|
||||
public string DateIso8601 => Date.ToString("o");
|
||||
public string EventMessage => JsonSerializer.Serialize(Event);
|
||||
|
||||
public User? User { get; set; }
|
||||
public OrganizationUserUserDetails? User { get; set; }
|
||||
public string? UserName => User?.Name;
|
||||
public string? UserEmail => User?.Email;
|
||||
public OrganizationUserType? UserType => User?.Type;
|
||||
|
||||
public User? ActingUser { get; set; }
|
||||
public OrganizationUserUserDetails? ActingUser { get; set; }
|
||||
public string? ActingUserName => ActingUser?.Name;
|
||||
public string? ActingUserEmail => ActingUser?.Email;
|
||||
public OrganizationUserType? ActingUserType => ActingUser?.Type;
|
||||
|
||||
public Group? Group { get; set; }
|
||||
public string? GroupName => Group?.Name;
|
||||
|
||||
public Organization? Organization { get; set; }
|
||||
public string? OrganizationName => Organization?.DisplayName();
|
||||
|
||||
@@ -97,4 +97,15 @@ public interface IOrganizationUserRepository : IRepository<OrganizationUser, Gui
|
||||
/// <param name="organizationUserToConfirm">Accepted OrganizationUser to confirm</param>
|
||||
/// <returns>True, if the user was updated. False, if not performed.</returns>
|
||||
Task<bool> ConfirmOrganizationUserAsync(AcceptedOrganizationUserToConfirm organizationUserToConfirm);
|
||||
|
||||
/// <summary>
|
||||
/// Returns the OrganizationUserUserDetails if found.
|
||||
/// </summary>
|
||||
/// <param name="organizationId">The id of the organization</param>
|
||||
/// <param name="userId">The id of the User to fetch</param>
|
||||
/// <returns>OrganizationUserUserDetails of the specified user or null if not found</returns>
|
||||
/// <remarks>
|
||||
/// Similar to GetByOrganizationAsync, but returns the user details.
|
||||
/// </remarks>
|
||||
Task<OrganizationUserUserDetails?> GetDetailsByOrganizationIdUserIdAsync(Guid organizationId, Guid userId);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.Text.Json;
|
||||
using Bit.Core.AdminConsole.Models.Data.EventIntegrations;
|
||||
using Bit.Core.AdminConsole.Repositories;
|
||||
using Bit.Core.AdminConsole.Utilities;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Models.Data;
|
||||
@@ -13,8 +14,9 @@ public class EventIntegrationHandler<T>(
|
||||
IEventIntegrationPublisher eventIntegrationPublisher,
|
||||
IIntegrationFilterService integrationFilterService,
|
||||
IIntegrationConfigurationDetailsCache configurationCache,
|
||||
IUserRepository userRepository,
|
||||
IGroupRepository groupRepository,
|
||||
IOrganizationRepository organizationRepository,
|
||||
IOrganizationUserRepository organizationUserRepository,
|
||||
ILogger<EventIntegrationHandler<T>> logger)
|
||||
: IEventMessageHandler
|
||||
{
|
||||
@@ -89,19 +91,35 @@ public class EventIntegrationHandler<T>(
|
||||
{
|
||||
var context = new IntegrationTemplateContext(eventMessage);
|
||||
|
||||
if (IntegrationTemplateProcessor.TemplateRequiresGroup(template) && eventMessage.GroupId.HasValue)
|
||||
{
|
||||
context.Group = await groupRepository.GetByIdAsync(eventMessage.GroupId.Value);
|
||||
}
|
||||
|
||||
if (eventMessage.OrganizationId is not Guid organizationId)
|
||||
{
|
||||
return context;
|
||||
}
|
||||
|
||||
if (IntegrationTemplateProcessor.TemplateRequiresUser(template) && eventMessage.UserId.HasValue)
|
||||
{
|
||||
context.User = await userRepository.GetByIdAsync(eventMessage.UserId.Value);
|
||||
context.User = await organizationUserRepository.GetDetailsByOrganizationIdUserIdAsync(
|
||||
organizationId: organizationId,
|
||||
userId: eventMessage.UserId.Value
|
||||
);
|
||||
}
|
||||
|
||||
if (IntegrationTemplateProcessor.TemplateRequiresActingUser(template) && eventMessage.ActingUserId.HasValue)
|
||||
{
|
||||
context.ActingUser = await userRepository.GetByIdAsync(eventMessage.ActingUserId.Value);
|
||||
context.ActingUser = await organizationUserRepository.GetDetailsByOrganizationIdUserIdAsync(
|
||||
organizationId: organizationId,
|
||||
userId: eventMessage.ActingUserId.Value
|
||||
);
|
||||
}
|
||||
|
||||
if (IntegrationTemplateProcessor.TemplateRequiresOrganization(template) && eventMessage.OrganizationId.HasValue)
|
||||
if (IntegrationTemplateProcessor.TemplateRequiresOrganization(template))
|
||||
{
|
||||
context.Organization = await organizationRepository.GetByIdAsync(eventMessage.OrganizationId.Value);
|
||||
context.Organization = await organizationRepository.GetByIdAsync(organizationId);
|
||||
}
|
||||
|
||||
return context;
|
||||
|
||||
@@ -26,7 +26,7 @@ public static partial class IntegrationTemplateProcessor
|
||||
return match.Value; // Return unknown keys as keys - i.e. #Key#
|
||||
}
|
||||
|
||||
return property?.GetValue(values)?.ToString() ?? "";
|
||||
return property.GetValue(values)?.ToString() ?? string.Empty;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -38,7 +38,8 @@ public static partial class IntegrationTemplateProcessor
|
||||
}
|
||||
|
||||
return template.Contains("#UserName#", StringComparison.Ordinal)
|
||||
|| template.Contains("#UserEmail#", StringComparison.Ordinal);
|
||||
|| template.Contains("#UserEmail#", StringComparison.Ordinal)
|
||||
|| template.Contains("#UserType#", StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
public static bool TemplateRequiresActingUser(string template)
|
||||
@@ -49,7 +50,18 @@ public static partial class IntegrationTemplateProcessor
|
||||
}
|
||||
|
||||
return template.Contains("#ActingUserName#", StringComparison.Ordinal)
|
||||
|| template.Contains("#ActingUserEmail#", StringComparison.Ordinal);
|
||||
|| template.Contains("#ActingUserEmail#", StringComparison.Ordinal)
|
||||
|| template.Contains("#ActingUserType#", StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
public static bool TemplateRequiresGroup(string template)
|
||||
{
|
||||
if (string.IsNullOrEmpty(template))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return template.Contains("#GroupName#", StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
public static bool TemplateRequiresOrganization(string template)
|
||||
|
||||
@@ -688,4 +688,21 @@ public class OrganizationUserRepository : Repository<OrganizationUser, Guid>, IO
|
||||
|
||||
return rowCount > 0;
|
||||
}
|
||||
|
||||
public async Task<OrganizationUserUserDetails?> GetDetailsByOrganizationIdUserIdAsync(Guid organizationId, Guid userId)
|
||||
{
|
||||
using (var connection = new SqlConnection(ConnectionString))
|
||||
{
|
||||
var result = await connection.QuerySingleOrDefaultAsync<OrganizationUserUserDetails>(
|
||||
"[dbo].[OrganizationUserUserDetails_ReadByOrganizationIdUserId]",
|
||||
new
|
||||
{
|
||||
OrganizationId = organizationId,
|
||||
UserId = userId
|
||||
},
|
||||
commandType: CommandType.StoredProcedure);
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -965,4 +965,20 @@ public class OrganizationUserRepository : Repository<Core.Entities.OrganizationU
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
#nullable enable
|
||||
|
||||
public async Task<OrganizationUserUserDetails?> GetDetailsByOrganizationIdUserIdAsync(Guid organizationId, Guid userId)
|
||||
{
|
||||
using (var scope = ServiceScopeFactory.CreateScope())
|
||||
{
|
||||
var dbContext = GetDatabaseContext(scope);
|
||||
var view = new OrganizationUserUserDetailsViewQuery();
|
||||
var entity = await view.Run(dbContext).SingleOrDefaultAsync(ou => ou.OrganizationId == organizationId && ou.UserId == userId);
|
||||
return entity;
|
||||
}
|
||||
}
|
||||
#nullable disable
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ using Bit.Core.AdminConsole.Models.Business.Tokenables;
|
||||
using Bit.Core.AdminConsole.Models.Data.EventIntegrations;
|
||||
using Bit.Core.AdminConsole.Models.Teams;
|
||||
using Bit.Core.AdminConsole.OrganizationFeatures.Policies;
|
||||
using Bit.Core.AdminConsole.Repositories;
|
||||
using Bit.Core.AdminConsole.Services;
|
||||
using Bit.Core.AdminConsole.Services.Implementations;
|
||||
using Bit.Core.AdminConsole.Services.NoopImplementations;
|
||||
@@ -889,8 +890,9 @@ public static class ServiceCollectionExtensions
|
||||
eventIntegrationPublisher: provider.GetRequiredService<IEventIntegrationPublisher>(),
|
||||
integrationFilterService: provider.GetRequiredService<IIntegrationFilterService>(),
|
||||
configurationCache: provider.GetRequiredService<IIntegrationConfigurationDetailsCache>(),
|
||||
userRepository: provider.GetRequiredService<IUserRepository>(),
|
||||
groupRepository: provider.GetRequiredService<IGroupRepository>(),
|
||||
organizationRepository: provider.GetRequiredService<IOrganizationRepository>(),
|
||||
organizationUserRepository: provider.GetRequiredService<IOrganizationUserRepository>(),
|
||||
logger: provider.GetRequiredService<ILogger<EventIntegrationHandler<TConfig>>>()
|
||||
)
|
||||
);
|
||||
@@ -1016,8 +1018,9 @@ public static class ServiceCollectionExtensions
|
||||
eventIntegrationPublisher: provider.GetRequiredService<IEventIntegrationPublisher>(),
|
||||
integrationFilterService: provider.GetRequiredService<IIntegrationFilterService>(),
|
||||
configurationCache: provider.GetRequiredService<IIntegrationConfigurationDetailsCache>(),
|
||||
userRepository: provider.GetRequiredService<IUserRepository>(),
|
||||
groupRepository: provider.GetRequiredService<IGroupRepository>(),
|
||||
organizationRepository: provider.GetRequiredService<IOrganizationRepository>(),
|
||||
organizationUserRepository: provider.GetRequiredService<IOrganizationUserRepository>(),
|
||||
logger: provider.GetRequiredService<ILogger<EventIntegrationHandler<TConfig>>>()
|
||||
)
|
||||
);
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
CREATE PROCEDURE [dbo].[OrganizationUserUserDetails_ReadByOrganizationIdUserId]
|
||||
@OrganizationId UNIQUEIDENTIFIER,
|
||||
@UserId UNIQUEIDENTIFIER
|
||||
AS
|
||||
BEGIN
|
||||
SET NOCOUNT ON
|
||||
|
||||
SELECT
|
||||
*
|
||||
FROM
|
||||
[dbo].[OrganizationUserUserDetailsView]
|
||||
WHERE
|
||||
[OrganizationId] = @OrganizationId
|
||||
AND
|
||||
[UserId] = @UserId
|
||||
END
|
||||
GO
|
||||
Reference in New Issue
Block a user