Base solution for your next web application

Activities of "codescientists"

https://github.com/aspnetboilerplate/module-zero-core-template/blob/master/aspnet-core/src/AbpCompanyName.AbpProjectName.Web.Core/Authentication/External/ExternalAuthManager.cs

From the Extensions menu in VS you can manage extensions and disable auto-updates.

Since it already auto-updated for me (as far as I know it can't be downgraded although surely there is a way in VS?), I was forced to upgrade our AspNetZero to 10.2 since I was in the middle of something heavily depending on the "radtool" and it suddenly stopped working. I'm very concerned to see that the extension would actually do this, especially without developers' control/awareness as to the timing of the update.

Version: 10.0 angular & .net5 Power Tools extension: v2.7.7 (apparently just updated on 3/25/21)

AspNetZeroRadTool seems to have had some breaking changes which are occurring only recently, and the main .DLL itself is somehow updating, along with all the FileTemplates. The new templates seem to use a structure that is not compatible with the angular source that I am using.

Given that the Power Tools extension just updated on 3/25 (since unfortunately extension auto-updates were turned on), while I understand it as merely a UI, it appears to be updating AspNetZeroRadTool and the associated file templates.

Is it possible to reverse (and keep reversed) the version of the RadTool DLL and/or the templates? Any time I generate a new entity the DLL and templates are replaced.

The file templates assume a structure that is simply not present in the angular UI for v10.0. The primary issue I have seen is with: aspnet-core\AspNetZeroRadTool\FileTemplates\Client\Angular\ModuleTemplate\MainTemplate.txt aspnet-core\AspNetZeroRadTool\FileTemplates\Client\Angular\ModuleTemplate\PartialTemplate.txt

Which result in modules (previously there were only components), with these import lines: import { AppSharedModule } from "@app/shared/app-shared.module"; import { AdminSharedModule } from "@app/admin/shared/admin-shared.module"; But no such modules exist. Is Power Tools only set up to assume some particular version of AspNetZero? Is it at all possible to back up to the VS extension's prior version? Shouldn't/count the extension (or the underlying RadTools) be aware of the versioning for the AspNetZero project it is modifying? (Updating aspnetzero itself to 10.2 is on our radar but is by no means practical right now. I can see that it has the two modules in question).

  • What is your product version? 10.0
  • What is your product type (Angular or MVC)? Angular
  • What is product framework type (.net framework or .net core)? Core
  • What is ABP Framework version? ABP 6.0

How can you acquire more than one DbContext instance for the same database? I was expecting to be able to inject multiple repositories into a service and have each use their own DbContext.

The purpose is so that we can run some "parallel" select queries (async/awaiting the SQL response) where concurrency is not a big concern. But this cannot be done if the underlying DbContext is the same instance.

Some simplified code to illustrate: // Repository implementation. Note: IMyRepository includes a GetDbContext() public class MyRepositoryBase<TEntity> : EfCoreRepositoryBase<MyDbContext, TEntity, long>, IMyRepository<TEntity> where TEntity : class, IEntity<long> { public MyRepositoryBase(IDbContextProvider<MyDbContext> dbContextProvider) : base(dbContextProvider) { } } and elsewhere:

// Testing from service var firstRepo = IocManager.Instance.Resolve<IMyRepository>();

var secondRepo = IocManager.Instance.Resolve<IMyRepository>();

bool theseMatch = object.Equals(firstRepo.GetDbContext(), secondRepo.GetDbContext());

// Since DBContext is same instance, cannot await these as they run concurrently... var gotDispatches = firstRepo.GetAllListAsync(); var gotDeliveries = secondRepo.GetAllListAsync(); await Task.WhenAll(gotDispatches, gotDeliveries); ` How can I enforce that the repositories each have their own DbContext, as though they were separate API requests. From looking at ABP source it seems like the IDbContextProvider injected into the repository base is going to always provide the same DbContext for the same unit of work. Is there no way to configure it otherwise?

In terms of dependency injection, I want the DbContexts to be transient just like the service implementations, with one new instance per resolve. Would I need to create a custom IDbContextProvider that just always provided a new DbContext? Is there a better/easier way? What might this break?

Prerequisites:

  • What is your product version? 10.0
  • What is your product type (Angular or MVC)? Angular
  • What is product framework type (.net framework or .net core)? .net core

I have noticed that a few of the ApplicationServices in OurProject.Application make use of the Aspnetcore AuthorizeAttributeat class or method-leve, instead of AbpAuthorizeAttribute, namely these: DynamicPropertyAppService, DynamicPropertyValueAppService, DynamicEntityPropertyAppService, DynamicEntityPropertyValueAppService PaymentAppService

But it does not seem that this attribute can do anything at the service layer, since these are not aspnetcore controllers. In practice it appears that unauthorized calls can be made. Should I replace with AbpAuthorize? Other services seem to use this, and when used, unauthorized calls are rejected.

Question

Using Version 10.0, Angular/Core

I have tested the two-factor auth (only with email) and am seeing some issues (haven't found these from searching so far).

  1. If 2FA is enabled & active for a user they can log in the first time. If they log out and log back in (with 2FA code each time) it will work. But after a while we will always get "Security code could not be sent!". I notice that the cache is set early (in TokenController.Authenticate instead of at the time where the code is generated in TokenController.SendTwoFactorAuthCode). From debug I find that the call to ITypedCache<string,TwoFactorCodeCacheItem>.Set() does NOT actually set in values in memory, past a certain point in time.
  2. I notice the cache has two different "expiration" settings. Looking in the [project]WebCoreModule.cs I can see that for the 2-factor code cache, the cache's DefaultAbsoluteExpireTime is set. In debug I can see that this is configured once on first instance of needing the 2-factor code cache. It is set to 2 minutes. So it seems like if an absolute expire time is set for the whole cache, no entries are settable or retrievable after that time. I don't know if this can be confirmed from the ABP code underlying but it seems to be what's happening. Why is DefaultSlidingExpireTimenot used instead? This seems to fix the issue, and allows a new expiration "per item" instead of one global/permanent expiration for all future cache entries. Could this be happening with other cache-based operations? I am only just getting started with our project.
  3. In the angular UI, once the code is sent, a timer indicates "90 seconds" but this is unrelated to the 2 minutes established on the API side. I can see this is hard-coded. Shouldn't the API return info about how long the code will last at the time it is generated?

Still occurs. But apparently it comes from Microsoft.Extensions.Identity.Core.UserManager base class. The line where the "new" code is generated is from TokenAuthController.SendTwoFactorAuthCode(): cacheItem.Code = await _userManager.GenerateTwoFactorTokenAsync(user, model.Provider);

I don't understand why it is the same number but it often is, perhaps depending on timing? Indeed responses here suggest it is (I assume aspnetcore equivalents came out of MVC). Also implies possibly some way to change it. Could just randomly generate a code some other way since it is generated & checked against a cache.

https://stackoverflow.com/questions/42369268/how-to-prevent-generation-of-the-same-otps-in-mvc-2fa

  • What is your product version? Version 10.0 / ABP 6.0
  • What is your product type (Angular or MVC)? Angular
  • What is product framework type (.net framework or .net core)? .NET Core (.NET 5)

I find that I do not know what differences to expect nor how to operate properly when MultitenancyEnabled = false is set. This seems to be a pandora's box of related questions but l will ask in order of immediate relevance:

  1. How does one login as the global admin (email:[email protected], TenantId:null)? Whenever we login as admin/123qwe it assumes the default tenant, and logs in the more "limited" admin.
  2. How does one access admin/host-settings in the Angular UI? It appears that the "secondary" admin (email:[email protected], TenantId:1) cannot access this menu since they do not have privileges.
  3. What database changes should be expected upon re-running EF core database update after turning off Multitenancy? I have not been able to discern any. I thought maybe some linkages or tables related to multitenancy might go away. Previous forum answers suggest that updating the database might be the missing factor if multitenancy still seems active.
  4. Does TenantId == 1 become the standard for all new data entities, or would it be TenantId == null, or no such field? Should new entities implement IMustHaveTenant, or IMayHaveTenant, or neither? Again, the assumption is we could steer clear of Multitenancy entirely, so I would think they should not have to implement any TenantId property. If this is not true, then what is the real expectation. The angular UI has code which suggests the multi-tenancy "side" is Tenant any time TenantID>0, and Host any time TenantID is 0 or null. From our perspective there should be no "side" but it's looking like that is not really an option.

In general it is looking like there is a lot to work around or step around when it comes to treating this as a single site without multi-tenancy. Admin users should be able to edit any settings like these (as examples) from one place, or at least from one login:

hostSettings.externalLoginProviderSettings.facebook.appId
hostSettings.userManagement.smsVerificationEnabled
hostSettings.userManagement.useCaptchaOnLogin
hostSettings.userManagement.sessionTimeOutSettings.isEnabled
settings.userManagement.useCaptchaOnLogin // ??
settings.security.useDefaultPasswordComplexitySettings
settings.userManagement.isNewRegisteredUserActiveByDefault

If we access Settings in the angular client from the "real"/host admin user, will these settings all be combined? The client seems to be built to assume a Tenant Id.

Errors involve missing QAUser. This is a test post and I'll delete it if I see it post.

Db update after deleting database doesn't seem to produce any differences. I also generated a migration but it was empty. I always get 2 admin users, one with Tenant ID == null, one with Tenant ID == 1. The Angular UI code suggests TenantID > 0 is what makes something multi-tenant. I can only login with the multi-tenant version of 'admin' (email address = [email protected], and TenantID == 1).

Once we turn off multi-tenancy, should new entities we create still need a TenantID? If so, should it be null, or 0, or 1? How do I login with the true 'admin'? How do I access settings such as hostSettings.userManagement.smsVerificationEnabled which cannot be edited from the UI for the 'tenant' side? What kinds of settings are going to remain conceptually divided between 'tenant' and 'host'? The whole idea is that we should not have to write an API client that knows or cares about 'tenant' because there is only one host/tenant and that is the API as a whole. How can we properly work around, cover up, and step over this concept with as little complexity as possible?

Sorry, I can't post a new post because the forum posting seems to be broken for me. I'm not sure if I can even reply on this thread.

Showing 1 to 10 of 10 entries