Hello smansuri
Can you please share your app.module.ts
& package.json
so that I can reproduce the same issue.
Mostly this error occurs when we don't add any service file in module file providers array. You can do one this in angular.json
file if you make "sourceMap": true,
in configurations with this you can check some more details of error.
I am not able to reproduce please guide me if possible.
Thank you
Hi Anjali,
It's not working as well. Actually the same error appier if you will generate a new project based on a microservice template with Blazor WASM by abp suite v7.4.0.
Cheers, Iulian
let me check and get back to you
Hi
to enable captcha
you follow this
https://support.abp.io/QA/Questions/489/How-to-enable-reCaptcha-in-ABP?_ga=2.177433699.75017784.1696827709-327044615.1686624402
i am confused why are you asking for angular code snippets, can you please explain?
read more about account module
https://docs.abp.io/en/commercial/latest/modules/account
All these you can override in AuthServer Project which is in mvc the previous registeration code that i share you have to put that in MVC authserver project.
read more about https://docs.abp.io/en/commercial/latest/modules/payment
if you want to do the registration in angular. you just have to do the convert the code inside RegisterLocalUserAsync()
to angular which are basically httpcalls, please refer to angular documentation about how to make http requests
https://angular.io/api/common/http/HttpClient
Are you really sure that you want to allow anonymous access to that?
what is the exact flow?
depending on your specific needs, you may want to create your own registration flow. Just a suggestion based on what you wrote:
Upon registration, you may create a form where you ask for the information you need to build a tenant. Create your own appservice for that, where registration alone can be done without the requirement of being logged in. When the user registrates -> you create a tenant with the information you need, based on what the user specified. First create a tenant, then create a new user in that tenant.
After that, you'll end up with a fresh tenant with a user inside. The rest can be done with an authorized user. You would not need to expose too many things.
In addition, you may want to store information about the registration state to allow for clean up scenarios.
In addition to the link you referred to: I think you can only change the permission needed, not disabling it entirely. You could try to add the
[AllowAnonymous]
attribute - but even if it works it would not be best practice to do that. Application Services handle specific needs. Your needs seem to be different from what the default provides. Therefore it's best to create your own implementation of Tenant/ User creation.
jfistelmann i will look into this. thanks
Hi
Yes instead of that you can create your own RegisterTenant Page in authserver and register a client with client_credentials
flow
Step 1 : In OpenIddictDataSeedContributor
register a client wit client_credentials flow make sure you run migrator on a empty db or delete data from the openidApplication table
// BookStore_Web_Account
var bookStore_Web_AccountClientId = configurationSection["BookStore_Web_Account:ClientId"];
if (!bookStore_Web_AccountClientId.IsNullOrWhiteSpace())
{
var bookStore_Web_AccountClientIdRootUrl = configurationSection["BookStore_Web_Account:RootUrl"]?.TrimEnd('/');
await CreateApplicationAsync(
name: bookStore_Web_AccountClientId!,
type: OpenIddictConstants.ClientTypes.Confidential,
consentType: OpenIddictConstants.ConsentTypes.Implicit,
displayName: "Swagger Application",
secret: configurationSection["BookStore_Web_Account:ClientSecret"] ?? "1q2w3e*",
grantTypes: new List<string> {OpenIddictConstants.GrantTypes.ClientCredentials },
scopes: new List<string> { "BookStore" },
clientUri: bookStore_Web_AccountClientIdRootUrl,
logoUri: "/images/clients/swagger.svg",
permissions: new List<string>
{
"Saas.Tenants",
"Saas.Tenants.Create",
"Saas.Tenants.Update",
"Saas.Tenants.ManageConnectionStrings",
"Saas.Tenants.SetPassword",
"Saas.Editions",
"Saas.Editions.Create",
"Saas.Editions.Update"
}
);
}
add this in dbmigrator appsetting.json
Step 2 Create your own RegisterTenant.cshtml create UI as it is in Register.cshtml Page in the Volo.Account.Pro module you can download the source code from abp suite.
in the RegisterTenant.cshtml.cs you can use this code make sure to create your own PostInput class just as it is in Register.cshtml.cs with the the extra fields that you need then you can use that to send it to tenant api..
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Net.Http.Headers;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.Account;
using Volo.Abp.Account.Public.Web.Pages.Account;
using Volo.Abp.Account.Public.Web.Security.Recaptcha;
using Volo.Abp.Identity.Settings;
using Volo.Abp.Settings;
using Volo.Abp.Uow;
using Volo.Saas.Host;
using IdentityUser = Volo.Abp.Identity.IdentityUser;
using Microsoft.Extensions.Configuration;
using System.Text.Json;
namespace Acme.BookStore.Pages.Account
{
public class RegisterTenantModel : RegisterModel
{
private readonly IConfiguration _configuration;
public RegisterTenantModel(IConfiguration configuration)
{
_configuration = configuration;
}
protected override async Task< IdentityUser > RegisterLocalUserAsync()
{
ValidateModel();
var captchaResponse = string.Empty;
if (UseCaptcha)
{
captchaResponse = HttpContext.Request.Form[RecaptchaValidatorBase.RecaptchaResponseKey];
}
string token = await GetClientCredentialsTokenAsync($"{_configuration["AuthServer:Authority"]?.EnsureEndsWith('/')}connect/token" ?? string.Empty, "BookStore_Web_Account", "1q2w3e*", new string[] { "BookStore" });
var tenant = new
{
name = "demo",
adminEmailAddress = "demo@demo.com",
adminPassword = "Welcome1$"
};
var tenantId = await CreateTenant(token, JsonSerializer.Serialize(tenant));
using (CurrentTenant.Change(tenantId))
{
var user = await UserManager.FindByEmailAsync("example@example.com");
if (user == null)
{
throw new UserFriendlyException("UserNotFound");
}
user.SetPhoneNumber("9999999999", false);
user.Name = "Demo";
user.Surname = "Demo";
await UserManager.UpdateAsync(user);
return user;
}
}
private async Task< Guid? > CreateTenant(string token,string body)
{
using (HttpClient client = new HttpClient())
{
var request = new HttpRequestMessage(HttpMethod.Post, $"{_configuration["RemoteServices:BaseUrl"]?.EnsureEndsWith('/')}api/saas/tenants");
request.Headers.Add("Authorization", $"Bearer {token}");
request.Content = new StringContent(body, null, "application/json");
var response = await client.SendAsync(request);
response.EnsureSuccessStatusCode();
var responseBody = await response.Content.ReadAsStringAsync();
var responseDeserilized = JsonSerializer.Deserialize<TenantResponse>(responseBody);
return responseDeserilized?.id;
}
}
private async Task< string > GetClientCredentialsTokenAsync(string tokenUrl, string clientId, string clientSecret, IEnumerable<string> scopes = null)
{
// Create a HttpClient to send the request to the token endpoint
using (HttpClient client = new HttpClient())
{
// Set the client credentials (client_id and client_secret) in the request headers
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.UTF8.GetBytes($"{clientId}:{clientSecret}")));
// Prepare the request content for the token endpoint
List<KeyValuePair< string, string > > requestContent = new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string>("grant_type", "client_credentials"),
};
// Add scopes, if provided
if (scopes != null)
{
requestContent.Add(new KeyValuePair<string, string>("scope", string.Join(" ", scopes)));
}
// Send the request to the token endpoint
HttpResponseMessage response = await client.PostAsync(tokenUrl, new FormUrlEncodedContent(requestContent));
// Check if the request was successful (status code 200)
if (response.IsSuccessStatusCode)
{
// Read the response content (which should contain the access token)
string responseContent = await response.Content.ReadAsStringAsync();
// Deserialize the response to extract the access token
dynamic responseData = JObject.Parse(responseContent);
string accessToken = responseData.access_token;
return accessToken;
}
else
{
// If the request was not successful, handle the error here
// You might want to log or throw an exception
throw new HttpRequestException($"Error getting access token. Status code: {response.StatusCode}");
}
}
}
}
public class TenantResponse
{
public Guid id { get; set; }
}
}
in this way you avoid making anything public or anonymous and only will be doable on the registeration page
Hello icoretchi,
Can you please run abp install-libs
command in your project folder
check this https://support.abp.io/QA/Questions/5874
please do let me know if it helps
Thanks, Anjali
Hello srgzibrahim@gmail.com,
Please check https://medium.com/volosoft/how-to-add-a-new-javascript-library-to-your-abp-project-62b21545f4cc
Please do let me know if it helps you
Thanks, Anjali
Hello smansuri,
please do have look to similar issues https://support.abp.io/QA/Questions/702/NullInjectorError-in-console-Angular-app-couldn%27t-load https://support.abp.io/QA/Questions/773/NullInjectorError-when-access-to-Permission-features
please do let me know if find helpful
Thanks, Anjali
Hello devpayoff,
Can you please try this I was able to repro and able to run the project with the below solution.
"configurations": {
"production": {
"optimization": false, // added
"budgets": [
{
"type": "initial",
"maximumWarning": "5mb", // updated
"maximumError": "8mb" // updated
},
{
"type": "anyComponentStyle",
"maximumWarning": "2kb",
"maximumError": "100kb"
}
],
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.prod.ts"
}
],
"outputHashing": "all"
},
Hello devpayoff,
I am able to reproduce the issue at my end and working on it.
can you please share yarn.lock file by which you are able to run project successfully so that I can better assist you.
Regards,