Files
QMAX/tests/QMax.Tests/TenantIsolationTests.cs
T

92 lines
4.0 KiB
C#

using Microsoft.Data.Sqlite;
using Microsoft.EntityFrameworkCore;
using QMax.Api.Data;
using QMax.Api.Data.Entities;
using QMax.Api.Infrastructure.Auth;
using QMax.Api.Configuration;
using QMax.Api.Contracts;
using QMax.Api.Controllers;
using QMax.Api.Infrastructure.Max;
using Microsoft.Extensions.Options;
namespace QMax.Tests;
public sealed class TenantIsolationTests
{
[Fact]
public async Task Phone_challenge_issues_tokens_only_after_max_code_completion()
{
await using var connection = new SqliteConnection("Data Source=:memory:");
await connection.OpenAsync();
var options = new DbContextOptionsBuilder<QMaxDbContext>().UseSqlite(connection).Options;
var currentUser = new CurrentUserAccessor();
await using var db = new QMaxDbContext(options, currentUser);
using (currentUser.Push(null, bypassTenantFilter: true)) await db.Database.EnsureCreatedAsync();
var qmax = Options.Create(new QMaxOptions
{
PairingCode = "invite",
JwtSecret = "tenant-test-secret-that-is-at-least-32-characters"
});
var controller = new AuthController(db, new TokenService(qmax), qmax, new MockMaxBridgeClient(), currentUser);
var started = await controller.BeginPhoneAuth(
new BeginPhoneAuthRequest("8 (900) 000-00-01", "test phone", "invite"),
CancellationToken.None);
var challenge = Assert.IsType<PhoneAuthChallengeResponse>(started.Value);
Assert.NotEqual(Guid.Empty, challenge.ChallengeId);
Assert.Empty(await db.UserSessions.IgnoreQueryFilters().ToArrayAsync());
var completed = await controller.CompletePhoneAuth(
new CompletePhoneAuthRequest(challenge.ChallengeId, challenge.ChallengeToken, "123456"),
CancellationToken.None);
var auth = Assert.IsType<AuthResponse>(completed.Value);
Assert.False(string.IsNullOrWhiteSpace(auth.AccessToken));
Assert.Single(await db.UserSessions.IgnoreQueryFilters().ToArrayAsync());
Assert.Equal("+79000000001", auth.User.PhoneNumber);
}
[Fact]
public async Task Chats_and_messages_are_visible_only_to_the_current_user()
{
await using var connection = new SqliteConnection("Data Source=:memory:");
await connection.OpenAsync();
var options = new DbContextOptionsBuilder<QMaxDbContext>().UseSqlite(connection).Options;
var currentUser = new CurrentUserAccessor();
var firstUser = new User { PhoneNumber = "+79000000001" };
var secondUser = new User { PhoneNumber = "+79000000002" };
await using (var setup = new QMaxDbContext(options, currentUser))
using (currentUser.Push(null, bypassTenantFilter: true))
{
await setup.Database.EnsureCreatedAsync();
setup.Users.AddRange(firstUser, secondUser);
await setup.SaveChangesAsync();
}
Guid firstChatId;
await using (var db = new QMaxDbContext(options, currentUser))
using (currentUser.Push(firstUser.Id))
{
var chat = new Chat { ExternalId = "same-max-chat", Title = "First" };
chat.Messages.Add(new Message { Text = "first secret", Direction = MessageDirection.Incoming });
db.Chats.Add(chat);
await db.SaveChangesAsync();
firstChatId = chat.Id;
}
await using (var db = new QMaxDbContext(options, currentUser))
using (currentUser.Push(secondUser.Id))
{
var chat = new Chat { ExternalId = "same-max-chat", Title = "Second" };
chat.Messages.Add(new Message { Text = "second secret", Direction = MessageDirection.Incoming });
db.Chats.Add(chat);
await db.SaveChangesAsync();
Assert.Single(await db.Chats.ToArrayAsync());
Assert.Equal("Second", (await db.Chats.SingleAsync()).Title);
Assert.Single(await db.Messages.ToArrayAsync());
Assert.False(await db.Chats.AnyAsync(x => x.Id == firstChatId));
}
}
}