hi
There are two integration services in the microservices project.
IPermissionIntegrationService and IIdentityUserIntegrationService
It is easy to add a new integration service to your module. https://docs.abp.io/en/abp/latest/Integration-Services
You can give it a try. Feel free to give feedback if you have any problems.
Thanks.
hi
The tenant(TenantId) is set when a user is created.
https://github.com/abpframework/abp/blob/dev/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUser.cs#L165
tenantTenantId of a user by ObjectHelpervar user = await UserManager.GetByIdAsync
ObjectHelper.TrySetProperty(user, x => x.TenantId, () => NewTenantId);
hi
I will check if I can reproduce it in a new 8.0 project.
Thanks.
The PR of ABP framework.
https://github.com/abpframework/abp/pull/19523
hi
I updated the code. Can you test the latest one?
I will try to find a better way.
hi
Try to override the protected override void PublishEventsForTrackedEntity(EntityEntry entry) method.
The key changes are:
if (entry.Properties.Where(x => x.IsModified).All(x => x.Metadata.IsForeignKey()))
{
// Skip if only foreign keys are changed.
break;
}
using System;
using System.Linq;
using Microsoft.EntityFrameworkCore;
using Volo.Abp.AuditLogging.EntityFrameworkCore;
using Volo.Abp.BackgroundJobs.EntityFrameworkCore;
using Volo.Abp.BlobStoring.Database.EntityFrameworkCore;
using Volo.Abp.Data;
using Volo.Abp.DependencyInjection;
using Volo.Abp.EntityFrameworkCore;
using Volo.Abp.FeatureManagement.EntityFrameworkCore;
using Volo.Abp.Identity;
using Volo.Abp.Identity.EntityFrameworkCore;
using Volo.Abp.LanguageManagement.EntityFrameworkCore;
using Volo.Abp.PermissionManagement.EntityFrameworkCore;
using Volo.Abp.SettingManagement.EntityFrameworkCore;
using Volo.Abp.TextTemplateManagement.EntityFrameworkCore;
using Volo.Saas.EntityFrameworkCore;
using Volo.Saas.Editions;
using Volo.Saas.Tenants;
using Volo.Abp.Gdpr;
using Volo.Abp.OpenIddict.EntityFrameworkCore;
using BugTracker.Examples;
using Microsoft.EntityFrameworkCore.ChangeTracking;
using Microsoft.EntityFrameworkCore.Metadata;
using Volo.Abp;
using Volo.Abp.EntityFrameworkCore.Modeling;
namespace BugTracker.EntityFrameworkCore;
[ReplaceDbContext(typeof(IIdentityProDbContext))]
[ReplaceDbContext(typeof(ISaasDbContext))]
[ConnectionStringName("Default")]
public class BugTrackerDbContext :
AbpDbContext<BugTrackerDbContext>,
IIdentityProDbContext,
ISaasDbContext
{
/* Add DbSet properties for your Aggregate Roots / Entities here. */
public DbSet<ParentEntity> ParentEntities { get; set; }
#region Entities from the modules
/* Notice: We only implemented IIdentityProDbContext and ISaasDbContext
* and replaced them for this DbContext. This allows you to perform JOIN
* queries for the entities of these modules over the repositories easily. You
* typically don't need that for other modules. But, if you need, you can
* implement the DbContext interface of the needed module and use ReplaceDbContext
* attribute just like IIdentityProDbContext and ISaasDbContext.
*
* More info: Replacing a DbContext of a module ensures that the related module
* uses this DbContext on runtime. Otherwise, it will use its own DbContext class.
*/
// Identity
public DbSet<IdentityUser> Users { get; set; }
public DbSet<IdentityRole> Roles { get; set; }
public DbSet<IdentityClaimType> ClaimTypes { get; set; }
public DbSet<OrganizationUnit> OrganizationUnits { get; set; }
public DbSet<IdentitySecurityLog> SecurityLogs { get; set; }
public DbSet<IdentityLinkUser> LinkUsers { get; set; }
public DbSet<IdentityUserDelegation> UserDelegations { get; set; }
public DbSet<IdentitySession> Sessions { get; set; }
// SaaS
public DbSet<Tenant> Tenants { get; set; }
public DbSet<Edition> Editions { get; set; }
public DbSet<TenantConnectionString> TenantConnectionStrings { get; set; }
#endregion
public BugTrackerDbContext(DbContextOptions<BugTrackerDbContext> options)
: base(options)
{
}
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
/* Include modules to your migration db context */
builder.ConfigurePermissionManagement();
builder.ConfigureSettingManagement();
builder.ConfigureBackgroundJobs();
builder.ConfigureAuditLogging();
builder.ConfigureIdentityPro();
builder.ConfigureOpenIddictPro();
builder.ConfigureFeatureManagement();
builder.ConfigureLanguageManagement();
builder.ConfigureSaas();
builder.ConfigureTextTemplateManagement();
builder.ConfigureBlobStoring();
builder.ConfigureGdpr();
/* Configure your own tables/entities inside here */
//builder.Entity<YourEntity>(b =>
//{
// b.ToTable(BugTrackerConsts.DbTablePrefix + "YourEntities", BugTrackerConsts.DbSchema);
// b.ConfigureByConvention(); //auto configure for the base class props
// //...
//});
builder.Entity<ParentEntity>(b =>
{
b.ToTable(BugTrackerConsts.DbTablePrefix + "ParentEntities",
BugTrackerConsts.DbSchema);
b.ConfigureByConvention(); //auto configure for the base class props
b.HasMany(x => x.SubEntities).WithOne();
});
builder.Entity<SubEntity>(b =>
{
b.ToTable(BugTrackerConsts.DbTablePrefix + "SubEntities",
BugTrackerConsts.DbSchema);
b.ConfigureByConvention(); //auto configure for the base class props
});
}
protected override void PublishEventsForTrackedEntity(EntityEntry entry)
{
switch (entry.State)
{
case EntityState.Added:
ApplyAbpConceptsForAddedEntity(entry);
EntityChangeEventHelper.PublishEntityCreatedEvent(entry.Entity);
break;
case EntityState.Modified:
ApplyAbpConceptsForModifiedEntity(entry);
if (entry.Properties.Any(x => x.IsModified && (x.Metadata.ValueGenerated == ValueGenerated.Never || x.Metadata.ValueGenerated == ValueGenerated.OnAdd)))
{
if (entry.Properties.Where(x => x.IsModified).All(x => x.Metadata.IsForeignKey()))
{
// Skip if only foreign keys are changed.
break;
}
if (entry.Entity is ISoftDelete && entry.Entity.As<ISoftDelete>().IsDeleted)
{
EntityChangeEventHelper.PublishEntityDeletedEvent(entry.Entity);
}
else
{
EntityChangeEventHelper.PublishEntityUpdatedEvent(entry.Entity);
}
}
break;
case EntityState.Deleted:
ApplyAbpConceptsForDeletedEntity(entry);
EntityChangeEventHelper.PublishEntityDeletedEvent(entry.Entity);
break;
}
if (EntityChangeOptions.Value.PublishEntityUpdatedEventWhenNavigationChanges)
{
foreach (var entityEntry in ChangeTracker.Entries().Where(x => x.State == EntityState.Unchanged && AbpEfCoreNavigationHelper.IsEntityEntryNavigationChanged(x)))
{
if (entityEntry.Entity is ISoftDelete && entityEntry.Entity.As<ISoftDelete>().IsDeleted)
{
EntityChangeEventHelper.PublishEntityDeletedEvent(entityEntry.Entity);
}
else
{
EntityChangeEventHelper.PublishEntityUpdatedEvent(entityEntry.Entity);
}
}
}
}
}
hi
Please make this repo private I have downloaded the sourecode.
Thanks.
hi.
I have asked. You should check your reverse proxy configuration.
hi
If no action is taken on the login screen for more than 2 minutes, it gives Verification failed, score below threshold error when the login button is clicked.
You can generate recaptcha code when submitting the Login form.
We will update our code to use the V3_Programmatically way.
https://github.com/maliming/reCAPTCHA/blob/master/demo/reCAPTCHA.Demo/Pages/V3_Programmatically.cshtml
I have updated our code.