Add multi-user MAX authentication and tenant isolation
This commit is contained in:
@@ -10,6 +10,7 @@ using QMax.Api.Data.Entities;
|
||||
using QMax.Api.Infrastructure.Hubs;
|
||||
using QMax.Api.Infrastructure.Max;
|
||||
using QMax.Api.Services;
|
||||
using QMax.Api.Infrastructure.Auth;
|
||||
|
||||
namespace QMax.Api.Controllers;
|
||||
|
||||
@@ -21,11 +22,8 @@ public sealed class MaxController(
|
||||
MaxBridgeSyncService syncService,
|
||||
QMaxDbContext db,
|
||||
IHubContext<QMaxHub> hubContext,
|
||||
ChatProjectionService projection,
|
||||
IOptions<QMaxOptions> options) : ControllerBase
|
||||
ChatProjectionService projection) : ControllerBase
|
||||
{
|
||||
private readonly QMaxOptions _options = options.Value;
|
||||
|
||||
[HttpGet("status")]
|
||||
public async Task<ActionResult<MaxBridgeStatusDto>> Status(CancellationToken cancellationToken)
|
||||
{
|
||||
@@ -37,7 +35,12 @@ public sealed class MaxController(
|
||||
[HttpPost("login/start")]
|
||||
public async Task<ActionResult<MaxBridgeStatusDto>> BeginLogin(BeginMaxLoginRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
var phone = string.IsNullOrWhiteSpace(request.PhoneNumber) ? _options.MaxPhoneNumber : request.PhoneNumber;
|
||||
var phone = request.PhoneNumber;
|
||||
if (string.IsNullOrWhiteSpace(phone))
|
||||
{
|
||||
var userId = User.GetUserId();
|
||||
phone = await db.Users.Where(x => x.Id == userId).Select(x => x.PhoneNumber).FirstOrDefaultAsync(cancellationToken);
|
||||
}
|
||||
if (string.IsNullOrWhiteSpace(phone))
|
||||
{
|
||||
return BadRequest("Phone number is required.");
|
||||
@@ -111,27 +114,28 @@ public sealed class MaxController(
|
||||
return BadRequest("Channel was joined but was not saved in QMAX.");
|
||||
}
|
||||
|
||||
await hubContext.Clients.All.SendAsync("ChatListInvalidated", cancellationToken);
|
||||
await hubContext.Clients.User(User.GetUserId().ToString()).SendAsync("ChatListInvalidated", cancellationToken);
|
||||
return projection.ToDto(chat);
|
||||
}
|
||||
|
||||
private async Task SaveStateAsync(MaxBridgeStatus status, CancellationToken cancellationToken)
|
||||
{
|
||||
var state = await db.MaxAccountStates.FirstOrDefaultAsync(x => x.Id == 1, cancellationToken);
|
||||
var userId = User.GetUserId();
|
||||
var state = await db.MaxAccountStates.FirstOrDefaultAsync(cancellationToken);
|
||||
if (state is null)
|
||||
{
|
||||
state = new MaxAccountState { Id = 1 };
|
||||
state = new MaxAccountState { UserId = userId };
|
||||
db.MaxAccountStates.Add(state);
|
||||
}
|
||||
|
||||
state.PhoneNumber = _options.MaxPhoneNumber;
|
||||
state.PhoneNumber = await db.Users.Where(x => x.Id == userId).Select(x => x.PhoneNumber).FirstOrDefaultAsync(cancellationToken) ?? "";
|
||||
state.Status = status.Status;
|
||||
state.IsAuthorized = status.IsAuthorized;
|
||||
state.LastUrl = status.Url;
|
||||
state.LastError = status.LastError;
|
||||
state.UpdatedAt = DateTimeOffset.UtcNow;
|
||||
await db.SaveChangesAsync(cancellationToken);
|
||||
await hubContext.Clients.All.SendAsync("MaxStatusChanged", ToDto(status), cancellationToken);
|
||||
await hubContext.Clients.User(userId.ToString()).SendAsync("MaxStatusChanged", ToDto(status), cancellationToken);
|
||||
}
|
||||
|
||||
private static MaxBridgeStatusDto ToDto(MaxBridgeStatus status)
|
||||
|
||||
Reference in New Issue
Block a user