mirror of
https://github.com/bitwarden/server
synced 2025-12-29 06:33:43 +00:00
Add Microsoft Teams integration (#6410)
* Add Microsoft Teams integration * Fix method naming error * Expand and clean up unit test coverage * Update with PR feedback * Add documentation, add In Progress logic/tests for Teams * Fixed lowercase Slack * Added docs; Updated PR suggestions; * Fix broken tests
This commit is contained in:
@@ -0,0 +1,12 @@
|
||||
using Bit.Core.Models.Teams;
|
||||
|
||||
namespace Bit.Core.AdminConsole.Models.Data.EventIntegrations;
|
||||
|
||||
public record TeamsIntegration(
|
||||
string TenantId,
|
||||
IReadOnlyList<TeamInfo> Teams,
|
||||
string? ChannelId = null,
|
||||
Uri? ServiceUrl = null)
|
||||
{
|
||||
public bool IsCompleted => !string.IsNullOrEmpty(ChannelId) && ServiceUrl is not null;
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
namespace Bit.Core.AdminConsole.Models.Data.EventIntegrations;
|
||||
|
||||
public record TeamsIntegrationConfigurationDetails(string ChannelId, Uri ServiceUrl);
|
||||
@@ -0,0 +1,38 @@
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Settings;
|
||||
|
||||
namespace Bit.Core.AdminConsole.Models.Data.EventIntegrations;
|
||||
|
||||
public class TeamsListenerConfiguration(GlobalSettings globalSettings) :
|
||||
ListenerConfiguration(globalSettings), IIntegrationListenerConfiguration
|
||||
{
|
||||
public IntegrationType IntegrationType
|
||||
{
|
||||
get => IntegrationType.Teams;
|
||||
}
|
||||
|
||||
public string EventQueueName
|
||||
{
|
||||
get => _globalSettings.EventLogging.RabbitMq.TeamsEventsQueueName;
|
||||
}
|
||||
|
||||
public string IntegrationQueueName
|
||||
{
|
||||
get => _globalSettings.EventLogging.RabbitMq.TeamsIntegrationQueueName;
|
||||
}
|
||||
|
||||
public string IntegrationRetryQueueName
|
||||
{
|
||||
get => _globalSettings.EventLogging.RabbitMq.TeamsIntegrationRetryQueueName;
|
||||
}
|
||||
|
||||
public string EventSubscriptionName
|
||||
{
|
||||
get => _globalSettings.EventLogging.AzureServiceBus.TeamsEventSubscriptionName;
|
||||
}
|
||||
|
||||
public string IntegrationSubscriptionName
|
||||
{
|
||||
get => _globalSettings.EventLogging.AzureServiceBus.TeamsIntegrationSubscriptionName;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,4 @@
|
||||
#nullable enable
|
||||
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Bit.Core.Models.Slack;
|
||||
|
||||
|
||||
41
src/Core/AdminConsole/Models/Teams/TeamsApiResponse.cs
Normal file
41
src/Core/AdminConsole/Models/Teams/TeamsApiResponse.cs
Normal file
@@ -0,0 +1,41 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Bit.Core.Models.Teams;
|
||||
|
||||
/// <summary>Represents the response returned by the Microsoft OAuth 2.0 token endpoint.
|
||||
/// See <see href="https://learn.microsoft.com/graph/auth-v2-user">Microsoft identity platform and OAuth 2.0
|
||||
/// authorization code flow</see>.</summary>
|
||||
public class TeamsOAuthResponse
|
||||
{
|
||||
/// <summary>The access token issued by Microsoft, used to call the Microsoft Graph API.</summary>
|
||||
[JsonPropertyName("access_token")]
|
||||
public string AccessToken { get; set; } = string.Empty;
|
||||
}
|
||||
|
||||
/// <summary>Represents the response from the <c>/me/joinedTeams</c> Microsoft Graph API call.
|
||||
/// See <see href="https://learn.microsoft.com/graph/api/user-list-joinedteams">List joined teams -
|
||||
/// Microsoft Graph v1.0</see>.</summary>
|
||||
public class JoinedTeamsResponse
|
||||
{
|
||||
/// <summary>The collection of teams that the user has joined.</summary>
|
||||
[JsonPropertyName("value")]
|
||||
public List<TeamInfo> Value { get; set; } = [];
|
||||
}
|
||||
|
||||
/// <summary>Represents a Microsoft Teams team returned by the Graph API.
|
||||
/// See <see href="https://learn.microsoft.com/graph/api/resources/team">Team resource type -
|
||||
/// Microsoft Graph v1.0</see>.</summary>
|
||||
public class TeamInfo
|
||||
{
|
||||
/// <summary>The unique identifier of the team.</summary>
|
||||
[JsonPropertyName("id")]
|
||||
public string Id { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>The name of the team.</summary>
|
||||
[JsonPropertyName("displayName")]
|
||||
public string DisplayName { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>The ID of the Microsoft Entra tenant for this team.</summary>
|
||||
[JsonPropertyName("tenantId")]
|
||||
public string TenantId { get; set; } = string.Empty;
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
using Microsoft.Bot.Connector.Authentication;
|
||||
|
||||
namespace Bit.Core.AdminConsole.Models.Teams;
|
||||
|
||||
public class TeamsBotCredentialProvider(string clientId, string clientSecret) : ICredentialProvider
|
||||
{
|
||||
private const string _microsoftBotFrameworkIssuer = AuthenticationConstants.ToBotFromChannelTokenIssuer;
|
||||
|
||||
public Task<bool> IsValidAppIdAsync(string appId)
|
||||
{
|
||||
return Task.FromResult(appId == clientId);
|
||||
}
|
||||
|
||||
public Task<string?> GetAppPasswordAsync(string appId)
|
||||
{
|
||||
return Task.FromResult(appId == clientId ? clientSecret : null);
|
||||
}
|
||||
|
||||
public Task<bool> IsAuthenticationDisabledAsync()
|
||||
{
|
||||
return Task.FromResult(false);
|
||||
}
|
||||
|
||||
public Task<bool> ValidateIssuerAsync(string issuer)
|
||||
{
|
||||
return Task.FromResult(issuer == _microsoftBotFrameworkIssuer);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user