Using the .NET SDK for App Management

I have…

I’m submitting a…

  • Regression (a behavior that stopped working in a new release)
  • Bug report
  • Performance issue
  • Documentation issue or request

Current behavior

I am building an application in which I’m using Squidex as an engine to manage content and metadata. My application will have the concept of Tenants, but tenant management will happen somewhere else. I was thinking of using the concept of Apps in squidex to separate tenants, i.e., I would like to create a dedicated App for each tenant that I have. Each request made to my API will contain a Tenant ID, and I use a separate database to manage the Tenant ID / Squidex App Name association. Based on the Tenant ID of an incoming request, I would like to create a dedicated App for that tenant, in case one doesn’t already exist.

From reading the documentation, it seems that the client doesn’t support multiple apps anymore: “The client no longer supports multiple Apps anymore. Use one client per App.”

Nonetheless, the client still seems to contain a method for App Creation:

PostAppAsync(CreateAppDto request, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken));

I have created a Factory to create a new client for incoming tenantId/appId combinations:

public sealed class SquidexClientFactory : ISquidexClientFactory
{
    private readonly ConcurrentDictionary<int, ISquidexClient> _clients = new();
    private readonly SquidexClientOptions _options;

    public SquidexClientFactory(IOptions<SquidexClientOptions> options) => _options = options.Value;

    public ISquidexClient GetOrCreate(int tenantId, string appId) =>
        _clients.GetOrAdd(tenantId, id => new SquidexClient(new SquidexOptions
        {
            AppName = appId,
            ClientId = _options.ClientId!,
            ClientSecret = _options.ClientSecret!,
            Url = _options.Url!,
        }));
}

And an example of a service method which I want to use for app creation:

public async Task Create(int tenantId, string appId)
    {
        var appClient = _clientFactory.GetOrCreate(tenantId, appId);

        await appClient.Apps.PostAppAsync(new CreateAppDto { Name = appId });
    }

This seems to work, since I can see an app being created in Squidex and also I can see a new app in the States_Apps collection; however, I cannot see this app in the squidex UI when I log in. If I create the app on the UI, it appears.

The client id and the client secret that I am using are statically set as part of appsettings, and also in the docker container:

squidex_squidex:
    container_name: "squidex"
    image: "squidex/squidex:7"
    ports:
      - 80:80
    environment:
      - URLS__BASEURL=http://localhost
      - EVENTSTORE__TYPE=MongoDB
      - EVENTSTORE__MONGODB__CONFIGURATION=mongodb://squidex_mongo
      - STORE__MONGODB__CONFIGURATION=mongodb://squidex_mongo
      - IDENTITY__ADMINEMAIL=${SQUIDEX_ADMINEMAIL}
      - IDENTITY__ADMINPASSWORD=${SQUIDEX_ADMINPASSWORD}
      - IDENTITY__ADMINCLIENTID=${SQUIDEX_ADMINCLIENTID}
      - IDENTITY__ADMINCLIENTSECRET=${SQUIDEX_ADMINCLIENTSECRET}
    healthcheck:
      test: ["CMD", "curl", "-f", "squidex:80/healthz"]
      start_period: 60s
    volumes:
      - '.docker/squidex/assets:/app/Assets'
    restart: unless-stopped
    networks:
      - internal
    depends_on:
      - squidex_mongo

I am not sure If I am using this API correctly, perhaps there’s a misconception from my side, or if there’s a bug in the SDK or UI.

Expected behavior

Newly created App is visible in the squidex UI.

Minimal reproduction of the problem

Example code to reproduce this:

var squidexFactory = new SquidexClientFactory(Options.Create<SquidexClientOptions>(new SquidexClientOptions
        {
            ClientId = "admin_client_development",
            ClientSecret =
                "...",
            Url = "http://localhost:80/"
        }));

        var createTenantAppService = new CreateSquidexTenantAppService(squidexFactory);
        
        await createTenantAppService.Create(1, Guid.NewGuid().ToString());
        await createTenantAppService.Create(2, Guid.NewGuid().ToString());

Environment

App Name: Dynamic

  • Self hosted with docker
  • Self hosted with IIS
  • Self hosted with other version
  • Cloud version

Version: 21.5.0

Browser:

  • Edge

You are doing everything right. But you have to add yourself as a contributor to the team. If you are not a contributor, but if you have admin permissions, you can still access your app by navigating to the right URL, but you will not see it. The UI is just not made for 100+ apps, if you have a few tenants.