cofoundry icon indicating copy to clipboard operation
cofoundry copied to clipboard

User Areas: When logged into Admin Area, allow access to other areas

Open HeyJoel opened this issue 6 years ago • 1 comments

When working with multiple user areas, for example having a login protected members area which is set as the default auth schema, it can be confusing that you cannot access that user area when logged in with a CMS Admin account (permissions exceptions). It feels like if you have the correct entity permissions, you should be able to view those pages.

The reason you get permissions errors is because if you're not logged into the members area (the default auth schema) then Cofoundry falls back to the anonymous user. To a certain extent this is by design; user areas are completely separate with separate user accounts, giving you the advantage of being able to content manage different auth states (e.g. a login or registration page) and get a true representation of use complex multi-area workflows when logged in to a Cofoundry admin accounts and browsing through the site.

Additionally a user area might have some custom data/settings associated with it that might not be initialized correctly for a Cofoundry admin account, so in some scenarios it makes sense to register multiple accounts.

The downside of this flexibility is that it can be an annoyance for simpler scenarios where you don't want to have to create an account for each user area just to update some of the pages.

To better understand some of these issues we first need to build out a more fully featured sample project with multiple user areas (see issue #190).

Some things we could do to make this better would be, when logged into the Cofoundry admin user area:

  • a) Allow you to specify a fallback user area when the default auth schema is not logged in
  • b) Provide a toggle a switch to view the site as under a different user area / role

HeyJoel avatar Apr 18 '18 11:04 HeyJoel

Here is a work-around to change the fall-back from the anonymous user to a Cofoundry admin user (if logged in):

NB: This overrides undocumented features that may change in future without warning

using Cofoundry.Core.DependencyInjection;
using Cofoundry.Domain;
using Cofoundry.Domain.Data;
using System.Threading.Tasks;

/// <summary>
/// Registers the service override with the DI container
/// </summary>
public class OverrideDependencyRegistration : IDependencyRegistration
{
    public void Register(IContainerRegister container)
    {
        var options = RegistrationOptions.Override();
        options.Lifetime = InstanceLifetime.Scoped;
        container.Register<IUserContextService, CofoundryUserAreaFallBackUserContextService>(options);
    }
}

/// <summary>
/// An override to the built-in UserContextService that falls back
/// to the Cofoundry admin user area if not logged in.
/// </summary>
public class CofoundryUserAreaFallBackUserContextService : IUserContextService
{
    private readonly UserContextService _baseUserContextService;

    public CofoundryUserAreaFallBackUserContextService(
        CofoundryDbContext dbContext,
        IUserSessionService userSessionService,
        UserContextMapper userContextMapper
        )
    {
        _baseUserContextService = new UserContextService(dbContext, userSessionService, userContextMapper);
    }

    public void ClearCache()
    {
        _baseUserContextService.ClearCache();
    }

    public async Task<IUserContext> GetCurrentContextAsync()
    {
        // Try and get the context for the default user area schema
        var cx = await _baseUserContextService.GetCurrentContextAsync();

        if (!cx.UserId.HasValue)
        {
            // If not logged in to the default, fallback to the admin user area
            cx = await _baseUserContextService.GetCurrentContextByUserAreaAsync(CofoundryAdminUserArea.AreaCode);
        }

        return cx;
    }

    public async Task<IUserContext> GetCurrentContextByUserAreaAsync(string userAreaCode)
    {
        return await _baseUserContextService.GetCurrentContextByUserAreaAsync(userAreaCode);
    }

    public async Task<IUserContext> GetSystemUserContextAsync()
    {
        return await _baseUserContextService.GetSystemUserContextAsync();
    }
}

HeyJoel avatar Apr 18 '18 11:04 HeyJoel