Example #1
0
    // Commands

    // [CommandHandler] inherited
    public override async Task SignIn(
        SignInCommand command, CancellationToken cancellationToken = default)
    {
        var(session, user, authenticatedIdentity) = command;
        var context = CommandContext.GetCurrent();

        if (Computed.IsInvalidating())
        {
            _ = GetAuthInfo(session, default);
            _ = GetSessionInfo(session, default);
            var invSessionInfo = context.Operation().Items.Get <SessionInfo>();
            if (invSessionInfo != null)
            {
                _ = GetUser(invSessionInfo.UserId, default);
                _ = GetUserSessions(invSessionInfo.UserId, default);
            }
            return;
        }

        if (!user.Identities.ContainsKey(authenticatedIdentity))
#pragma warning disable MA0015
        {
            throw new ArgumentOutOfRangeException(
                      $"{nameof(command)}.{nameof(SignInCommand.AuthenticatedIdentity)}");
        }
#pragma warning restore MA0015
        if (await IsSignOutForced(session, cancellationToken).ConfigureAwait(false))
        {
            throw Errors.ForcedSignOut();
        }

        var dbContext = await CreateCommandDbContext(cancellationToken).ConfigureAwait(false);

        await using var _1 = dbContext.ConfigureAwait(false);

        var isNewUser = false;
        var dbUser    = await Users
                        .GetByUserIdentity(dbContext, authenticatedIdentity, cancellationToken)
                        .ConfigureAwait(false);

        if (dbUser == null)
        {
            (dbUser, isNewUser) = await Users
                                  .GetOrCreateOnSignIn(dbContext, user, cancellationToken)
                                  .ConfigureAwait(false);

            if (isNewUser == false)
            {
                UserConverter.UpdateEntity(user, dbUser);
                await dbContext.SaveChangesAsync(cancellationToken).ConfigureAwait(false);
            }
        }
        else
        {
            user = user with {
                Id = DbUserIdHandler.Format(dbUser.Id)
            };
            UserConverter.UpdateEntity(user, dbUser);
            await dbContext.SaveChangesAsync(cancellationToken).ConfigureAwait(false);
        }

        var dbSessionInfo = await Sessions.GetOrCreate(dbContext, session.Id, cancellationToken).ConfigureAwait(false);

        var sessionInfo = SessionConverter.ToModel(dbSessionInfo);
        if (sessionInfo !.IsSignOutForced)
        {
            throw Errors.ForcedSignOut();
        }

        sessionInfo = sessionInfo with {
            LastSeenAt            = Clocks.SystemClock.Now,
            AuthenticatedIdentity = authenticatedIdentity,
            UserId = DbUserIdHandler.Format(dbUser.Id)
        };
        context.Operation().Items.Set(sessionInfo);
        context.Operation().Items.Set(isNewUser);
        await Sessions.Upsert(dbContext, sessionInfo, cancellationToken).ConfigureAwait(false);
    }