2024-10-28 17:12:13 +01:00
|
|
|
|
using System.Net;
|
|
|
|
|
using System.Net.Http.Headers;
|
|
|
|
|
using Bit.Api.Auth.Models.Request.Accounts;
|
2022-08-29 16:24:52 +02:00
|
|
|
|
using Bit.Api.IntegrationTest.Factories;
|
2024-10-28 17:12:13 +01:00
|
|
|
|
using Bit.Api.IntegrationTest.Helpers;
|
2022-08-29 16:24:52 +02:00
|
|
|
|
using Bit.Api.Models.Response;
|
2024-10-28 17:12:13 +01:00
|
|
|
|
using Bit.Core;
|
|
|
|
|
using Bit.Core.Billing.Enums;
|
|
|
|
|
using Bit.Core.Enums;
|
|
|
|
|
using Bit.Core.Models.Data;
|
|
|
|
|
using Bit.Core.Services;
|
|
|
|
|
using NSubstitute;
|
2022-08-29 16:24:52 +02:00
|
|
|
|
using Xunit;
|
|
|
|
|
|
|
|
|
|
namespace Bit.Api.IntegrationTest.Controllers;
|
|
|
|
|
|
|
|
|
|
public class AccountsControllerTest : IClassFixture<ApiApplicationFactory>
|
|
|
|
|
{
|
|
|
|
|
private readonly ApiApplicationFactory _factory;
|
|
|
|
|
|
|
|
|
|
public AccountsControllerTest(ApiApplicationFactory factory) => _factory = factory;
|
|
|
|
|
|
|
|
|
|
[Fact]
|
|
|
|
|
public async Task GetPublicKey()
|
|
|
|
|
{
|
|
|
|
|
var tokens = await _factory.LoginWithNewAccount();
|
|
|
|
|
var client = _factory.CreateClient();
|
|
|
|
|
|
|
|
|
|
using var message = new HttpRequestMessage(HttpMethod.Get, "/accounts/profile");
|
|
|
|
|
message.Headers.Authorization = new AuthenticationHeaderValue("Bearer", tokens.Token);
|
|
|
|
|
var response = await client.SendAsync(message);
|
|
|
|
|
|
|
|
|
|
response.EnsureSuccessStatusCode();
|
|
|
|
|
|
|
|
|
|
var content = await response.Content.ReadFromJsonAsync<ProfileResponseModel>();
|
2024-08-09 15:31:06 +02:00
|
|
|
|
Assert.NotNull(content);
|
2022-08-29 16:24:52 +02:00
|
|
|
|
Assert.Equal("integration-test@bitwarden.com", content.Email);
|
|
|
|
|
Assert.Null(content.Name);
|
|
|
|
|
Assert.False(content.EmailVerified);
|
|
|
|
|
Assert.False(content.Premium);
|
|
|
|
|
Assert.False(content.PremiumFromOrganization);
|
|
|
|
|
Assert.Equal("en-US", content.Culture);
|
|
|
|
|
Assert.Null(content.Key);
|
|
|
|
|
Assert.Null(content.PrivateKey);
|
|
|
|
|
Assert.NotNull(content.SecurityStamp);
|
|
|
|
|
}
|
2024-10-28 17:12:13 +01:00
|
|
|
|
|
|
|
|
|
[Fact]
|
|
|
|
|
public async Task PostEmailToken_WhenAccountDeprovisioningEnabled_WithManagedAccount_ThrowsBadRequest()
|
|
|
|
|
{
|
|
|
|
|
var email = await SetupOrganizationManagedAccount();
|
|
|
|
|
|
|
|
|
|
var tokens = await _factory.LoginAsync(email);
|
|
|
|
|
var client = _factory.CreateClient();
|
|
|
|
|
|
|
|
|
|
var model = new EmailTokenRequestModel
|
|
|
|
|
{
|
|
|
|
|
NewEmail = $"{Guid.NewGuid()}@example.com",
|
|
|
|
|
MasterPasswordHash = "master_password_hash"
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
using var message = new HttpRequestMessage(HttpMethod.Post, "/accounts/email-token")
|
|
|
|
|
{
|
|
|
|
|
Content = JsonContent.Create(model)
|
|
|
|
|
};
|
|
|
|
|
message.Headers.Authorization = new AuthenticationHeaderValue("Bearer", tokens.Token);
|
|
|
|
|
var response = await client.SendAsync(message);
|
|
|
|
|
|
|
|
|
|
Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode);
|
|
|
|
|
var content = await response.Content.ReadAsStringAsync();
|
|
|
|
|
Assert.Contains("Cannot change emails for accounts owned by an organization", content);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Fact]
|
|
|
|
|
public async Task PostEmail_WhenAccountDeprovisioningEnabled_WithManagedAccount_ThrowsBadRequest()
|
|
|
|
|
{
|
|
|
|
|
var email = await SetupOrganizationManagedAccount();
|
|
|
|
|
|
|
|
|
|
var tokens = await _factory.LoginAsync(email);
|
|
|
|
|
var client = _factory.CreateClient();
|
|
|
|
|
|
|
|
|
|
var model = new EmailRequestModel
|
|
|
|
|
{
|
|
|
|
|
NewEmail = $"{Guid.NewGuid()}@example.com",
|
|
|
|
|
MasterPasswordHash = "master_password_hash",
|
|
|
|
|
NewMasterPasswordHash = "master_password_hash",
|
|
|
|
|
Token = "validtoken",
|
|
|
|
|
Key = "key"
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
using var message = new HttpRequestMessage(HttpMethod.Post, "/accounts/email")
|
|
|
|
|
{
|
|
|
|
|
Content = JsonContent.Create(model)
|
|
|
|
|
};
|
|
|
|
|
message.Headers.Authorization = new AuthenticationHeaderValue("Bearer", tokens.Token);
|
|
|
|
|
var response = await client.SendAsync(message);
|
|
|
|
|
|
|
|
|
|
Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode);
|
|
|
|
|
var content = await response.Content.ReadAsStringAsync();
|
|
|
|
|
Assert.Contains("Cannot change emails for accounts owned by an organization", content);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private async Task<string> SetupOrganizationManagedAccount()
|
|
|
|
|
{
|
|
|
|
|
_factory.SubstituteService<IFeatureService>(featureService =>
|
|
|
|
|
featureService.IsEnabled(FeatureFlagKeys.AccountDeprovisioning).Returns(true));
|
|
|
|
|
|
|
|
|
|
// Create the owner account
|
|
|
|
|
var ownerEmail = $"{Guid.NewGuid()}@bitwarden.com";
|
|
|
|
|
await _factory.LoginWithNewAccount(ownerEmail);
|
|
|
|
|
|
|
|
|
|
// Create the organization
|
|
|
|
|
var (_organization, _) = await OrganizationTestHelpers.SignUpAsync(_factory, plan: PlanType.EnterpriseAnnually2023,
|
|
|
|
|
ownerEmail: ownerEmail, passwordManagerSeats: 10, paymentMethod: PaymentMethodType.Card);
|
|
|
|
|
|
|
|
|
|
// Create a new organization member
|
|
|
|
|
var (email, orgUser) = await OrganizationTestHelpers.CreateNewUserWithAccountAsync(_factory, _organization.Id,
|
|
|
|
|
OrganizationUserType.Custom, new Permissions { AccessReports = true, ManageScim = true });
|
|
|
|
|
|
|
|
|
|
// Add a verified domain
|
|
|
|
|
await OrganizationTestHelpers.CreateVerifiedDomainAsync(_factory, _organization.Id, "bitwarden.com");
|
|
|
|
|
|
|
|
|
|
return email;
|
|
|
|
|
}
|
2022-08-29 16:24:52 +02:00
|
|
|
|
}
|