I want to make a child entity full audited.
There is no UI in the CRUD generator.
When using Twilio and SmsMessage, add the ability to override the "From Number" in the SmsMessage.
We are going to associate a number with each user and have the SMS messages be in "personal" threads.
We are having issues with Blazorise Rich Text component.
The Blazorise help system requires a commercial license.
How can we get support from them?
Thanks.
In Blazor Server, I added the following in blazor-global-styles.css and both the logo and the logo icon were replaced when logged in.
:root {
--lpx-logo: url('/images/logo/logo.svg') !important;
--lpx-logo-icon: url('/images/logo/logo-icon.svg') !important;
}
I also added it to global-styles.css in order for it to affect the login screen as well.
You can refer to the ANZ documentation which is largely applicable for ABP
https://aspnetboilerplate.com/Pages/Documents/Zero/Organization-Units#common-use-cases
https://aspnetboilerplate.com/Pages/Documents/Articles%5CHow-To%5Cadd-custom-data-filter-ef-core
The second link covers the case when a User can be assigned to only one Org Unit. If your use case covers M:M assignments it gets a bit more complicate. Here is sample code (I'm a noob so FWIW):
Create a Customer UserClaimsPrincipalFactory and in it put
public async override Task<ClaimsPrincipal> CreateAsync(IdentityUser user) { var principal = await base.CreateAsync(user); var organizationUnits = await _identityUserManager.GetOrganizationUnitsAsync(user); foreach (OrganizationUnit org in organizationUnits) { principal.Identities.First().AddClaim(new Claim("OU", org.Code)); } return principal; }
In your DBContext
protected override Expression<Func<TEntity, bool>> CreateFilterExpression<TEntity>() { var expression = base.CreateFilterExpression<TEntity>(); if (typeof(IMayHaveOrganizationUnit).IsAssignableFrom(typeof(TEntity))) { var predicate = PredicateBuilder.New<OrganizationUnit>(); if (OrgUnitCodes == null || !OrgUnitCodes.Any()) { // If No organizations assigned to User, return no entities predicate = predicate.And(p => false); } else { foreach (var code in OrgUnitCodes) { predicate = predicate.Or(ou => ou.Code.StartsWith(code)); } } Expression<Func<TEntity, bool>> mayHaveOuFilter = e => !IsOrganizationUnitFilterEnabled || OrganizationUnits .Where(predicate) .Select(s => s.Id).Contains(((IMayHaveOrganizationUnit)e).OrganizationUnitId.Value) == IsOrganizationUnitFilterEnabled; expression = expression == null ? mayHaveOuFilter : CombineExpressions(expression, mayHaveOuFilter); } return expression; }
In my example, I was attempting to implement user -> roles, user -> organization based Data Filters in DbContext.
If the filter requires a "join query", it will not work because the predicate seems to run once and get fixed - so even if user changes the filter remains the same.
I think this is a related post: https://stackoverflow.com/questions/67820361/entity-framework-core-global-dynamic-query-filter/68318214#68318214
Using https://docs.microsoft.com/en-us/ef/core/modeling/dynamic-model might be a solution, but I feel like both ABP and EF don't want you to use Data Filter, EF Global Filters for anything other than simple comparisons that do not require a join (e.g., isActive == true).
sorry shobhit my code does not work
The filter expression is created once (first time entity is queried) and does not change regardless of current user.
You can refer to the ANZ documentation which is largely applicable for ABP
https://aspnetboilerplate.com/Pages/Documents/Zero/Organization-Units#common-use-cases
https://aspnetboilerplate.com/Pages/Documents/Articles%5CHow-To%5Cadd-custom-data-filter-ef-core
The second link covers the case when a User can be assigned to only one Org Unit. If your use case covers M:M assignments it gets a bit more complicate. Here is sample code (I'm a noob so FWIW):
Create a Customer UserClaimsPrincipalFactory and in it put
public async override Task<ClaimsPrincipal> CreateAsync(IdentityUser user)
{
var principal = await base.CreateAsync(user);
var organizationUnits = await _identityUserManager.GetOrganizationUnitsAsync(user);
foreach (OrganizationUnit org in organizationUnits)
{
principal.Identities.First().AddClaim(new Claim("OU", org.Code));
}
return principal;
}
In your DBContext
protected override Expression<Func<TEntity, bool>> CreateFilterExpression<TEntity>()
{
var expression = base.CreateFilterExpression<TEntity>();
if (typeof(IMayHaveOrganizationUnit).IsAssignableFrom(typeof(TEntity)))
{
var predicate = PredicateBuilder.New<OrganizationUnit>();
if (OrgUnitCodes == null || !OrgUnitCodes.Any())
{
// If No organizations assigned to User, return no entities
predicate = predicate.And(p => false);
}
else
{
foreach (var code in OrgUnitCodes)
{
predicate = predicate.Or(ou => ou.Code.StartsWith(code));
}
}
Expression<Func<TEntity, bool>> mayHaveOuFilter = e => !IsOrganizationUnitFilterEnabled
|| OrganizationUnits
.Where(predicate)
.Select(s => s.Id).Contains(((IMayHaveOrganizationUnit)e).OrganizationUnitId.Value)
== IsOrganizationUnitFilterEnabled;
expression = expression == null ? mayHaveOuFilter : CombineExpressions(expression, mayHaveOuFilter);
}
return expression;
}