92 lines
4.0 KiB
C#
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));
|
|
}
|
|
}
|
|
}
|