Customizing Tenant Queries
By default, Bloqs provides a built-in GetTenantsQuery that determines which tenants are visible to the user. You can override this query in your API and provide your own logic to decide who can see which tenants.
Example: Overriding GetTenantsQuery
GetTenantsQueryusing Bloqs.Api.Engine.DataAccess;
using Bloqs.App.Engine;
using Bloqs.App.Engine.Queries;
using Bloqs.App.Engine.Queries.AccessControl;
using Bloqs.App.Engine.Queries.Query;
using Templates.SampleApp.Models.Global;
namespace Templates.SampleApp.Api.Queries.AccessControl;
public class GetTenants(IDataServiceCreator dataServiceCreator)
: IQueryHandler<GetTenantsQuery, GetTenantsQueryResult>
{
public async Task<GetTenantsQueryResult> HandleAsync(
GetTenantsQuery query,
CancellationToken cancellationToken = default
)
{
var dataService = dataServiceCreator.GetDataService<Tenant>(
DataServiceCreatorArgs.Create<Tenant>(query.AppName, Constants.Tenant.NoTenantName)
);
// Example: filter tenants by OrganizationId (could come from user claims)
var currentUserOrgId = Guid.Parse("8a5a49b0-7f35-4f52-8e6b-d3a1cbead2b7");
var tenants = await dataService.QueryAsync(t => t.OrganizationId == currentUserOrgId) ?? [];
if (!tenants.Any(x => x.Name == Constants.Tenant.DefaultTenantName))
{
// Ensure the default tenant always exists
tenants = tenants.Concat(
[new Tenant() { Name = Constants.Tenant.DefaultTenantName }]
);
}
return new GetTenantsQueryResult() { Tenants = tenants };
}
}Key Points
Registering the handler To make this query available, the class must be marked with the
[QueryHandler]attribute. This tells Bloqs to register your handler and replace the default tenant query.QueryAsyncwith filters TheDataServiceexposes an overload ofQueryAsyncthat accepts an expression filter. For example:var tenants = await dataService.QueryAsync(t => t.OrganizationId == currentUserOrgId);This ensures filtering is applied directly at the database level, so only relevant tenants are retrieved.
Custom Models
In this sample, we customize the tenant model to link tenants directly to an organization.
Tenant
using Bloqs.App.Engine.Attributes;
namespace Templates.SampleApp.Models.Global;
public class Tenant : Bloqs.App.Engine.AccessControl.Tenant
{
[Title("Organization")]
[Relation(typeof(Organization))]
public Guid OrganizationId { get; set; }
}Organization
using Bloqs.App.Engine.Entities;
namespace Templates.SampleApp.Models.Global;
public class Organization : Entity
{
public required string Name { get; set; } = string.Empty;
}Why Customize?
Control who can see what tenants (e.g., only tenants linked to a user’s organization).
Use
QueryAsyncwith expressions to filter efficiently at the database level.Ensure that business rules are enforced at the API level.
Extend the Bloqs model with domain-specific relationships, like linking tenants to organizations.
Last updated