After update to Abp 2.3 my tenant creation is not working anymore.
The exception is been throwing when the roles are created:
//TenantAppService.cs
//We are working entities of new tenant, so changing tenant filter
using (CurrentUnitOfWork.SetTenantId(tenant.Id))
{
//Create static roles for new tenant
CheckErrors(await _roleManager.CreateStaticRoles(tenant.Id)); <-- Here
The exception:
Exception thrown: 'Abp.Authorization.AbpAuthorizationException' in
mscorlib.dll
Additional information: [At least one of these permissions must be granted]
I didn't change the TenantAppService that came from Module Zero, but if I remove the AbpAuthorize from class it works.
[AbpAuthorize(PermissionNames.Pages_Tenants)] //If removed works
public class TenantAppService : SeducaAppServiceBase, ITenantAppService
{
...
Tks.
The problem was AbpCache.
What I need to do is restart the app (cleaning everything) or call the api method (api/AbpCache/ClearAll)
reference: https://github.com/aspnetboilerplate/aspnetboilerplate/issues/573
It's solves all my problems with permissions
The user who is calling this method has to be granted permission with PermissionNames.Pages_Tenants.
Related
Background
I've created a working bot in C# but I'm failing to expand it to be a multi-tenant bot. I have created multiple bots in the Microsoft portal using this technique to identify themselves from the messaging endpoint:
https://example.com/api/messages/bot1
https://example.com/api/messages/bot2
https://example.com/api/messages/bot3
I can grab the LastSegment from the URL while in the MessagesController and store it in PrivateConversationData so I know which bot is talking in the current conversation. I intended use this stored 'bot id' in order to retrieve the Microsoft AppId & Password from the web.config (the bot's credentials are stored as a series of custom entries and not the standard appSettings as that only works for a single bot).
Credentials Problem
The authentication works well (nearly) as described here except when using async code with .ConfigureAwait(false) I can't get the HttpContext.Current as it becomes null when running on a different thread. This means I can't get the authenticated user's credentials either by looking them up in the web.config or by calling GetCredentialsFromClaims() since I've lost the authenticated user. If I use .ConfigureAwait(true) I just get deadlocks all over the place.
I have the credentials in the web.config but they are stored per bot and I need the 'bot id' from the URL above in order to get the credentials.
Question
The crux of the problem is: I need the URL to get the 'bot id' and I need the 'bot id' to get the credentials from the web.config but I can never reliably get access to the URL once I've passed a .ConfigureAwait(false) in the code. On the flip side, I can't get the 'bot id' from the PrivateConversationData since I need the bot's credentials in order to load it. A bit chicken and egg :-(
If anyone has any ideas of what I may be doing wrong or has an alternative approach to know which 'bot id' is currently executing I'd very much appreciate it.
Thanks
Please find below given the sample code.
public class StartUp {
public void Configuration(IAppBuilder app) {
var builder = new ContainerBuilder();
//Note: Initialize / register the Metadata Service that can bring the tenant details from the corresponding store
builder.RegisterType<TenantMetadataService>().As<ITenantMetadataService>();
//Note: This helps you in accessing the TenantMetadata from any constructor going forward after the below registry
builder.Register(ti => TenantMetadata.GetTenantMetadataFromRequest()).InstancePerRequest();
//TODO: Register the various services / controllers etc which may require the tenant details here
}
}
public class TenantMetadata {
public Guid TenantId { get;set; }
public Uri TenantUrl { get;set; }
public string TenantName { get;set; }
public static TenantMetadata GetTenantMetadataFromRequest() {
var context = HttpContext.Current;
//TODO: If you have any header like TenantId coming from the request, you can read and use it
var tenantIdFromRequestHeader = "";
//TODO: There will be a lazy cache that keeps building the data as new tenant's login or use the application
if(TenantCache.Contains(...))return TenantCache[Key];
//TODO: Do a look-up from the above step and then construct the metadata
var tenantMetadata = metadataSvc.GetTenantMetadata(...);
//TODO: If the data match does not happen from the Step2, build the cache and then return the value.
TenantCache.Add(key,tenantMetadata);
return tenantMetadata;
}
}
Note
The above code snippet uses the various service placeholders, cache and the other methods which will require to be used based on the designed application services. If you wish not to cache the tenant metadata, if it may contain some sensitive data, you can remove the caching implementation parts.
This implementation can be spread across all your web facing portals like your Web UI, Web Api and WebJobs etc so that it is same across all apps and it is easy to test and consume.
HTH.
I currently have an ASP.NET Web Api 2 application which, for the purposes of this question, manages 'Items'. ASP.NET Identity 2 is used to provide authentication for requests, and the data is handed by Entity Framework 6.
My aim is for the item's Owner property to be set automatically to the user who authenticated the POST request. Below is the code so far:
public async Task<IHttpActionResult> PostItem(Item item)
{
var userId = User.Identity.GetUserId();
var user = await UserManager.FindByIdAsync(userId);
// Set the Owner to the currently authenticated user
item.Owner = user;
db.Items.Add(item); // Exception Thrown Here
await db.SaveChangesAsync();
...
}
However, when the method is called, the following exception occurs. The current userId and user are being found correctly, yet there is still an issue adding the Item once its Owner property has been set.
A first chance exception of type 'System.InvalidOperationException'
occurred in EntityFramework.dll
Additional information: An entity object cannot be referenced by
multiple instances of IEntityChangeTracker.
The problem is that you're trying to track the same entity using two different contexts and that doesn't work. maybe you should look in your code and see which of your entities is being tracked by two context, It is possible since you are using a global variable (db) as a reference to your context.
I am using SQL Server R2 for my Database. Now I am getting this kind of error frequently :
An exception of type 'System.Data.Entity.Core.EntityCommandExecutionException' occurred in EntityFramework.SqlServer.dll but was not handled in user code
Additional information: An error occurred while executing the command definition. See the inner exception for details.
InnerException: {"Invalid column name 'someColumn'."}
Here in the model every thing is fine and in database also. I know this is due to cache in dbcontext. I want to clear and rebind the dbcontext every time when I run the project. I googled for the solution and I got this solution, but I am unable to do the desired operation after declaring like this.
public class EFDbContext: DbContext
{
public DbSet < utblCategoryMaster > utblCategoryMasters { get; set; }
public DbSet < utblsubCategoryMaster > utblSubCategoryMasters { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
}
}
I am new to MVC and I don't know how to refresh entity framework. Is there any solution?
Entity framework model caching is done only at the AppDomain level, so if you build you project, restart IIS or recycle the application pool the caching will be gone.
To quote from the link you shared:
The model for that context is then cached and is for all further instances of the context in the app domain.
I think the problem is , there is mismatch between the schema and the mapping file. Can you double check the database, connection string and schema/mapping files?
Some additional information can be gained by running SQL Profile, as it can show you the exact query that is being executed when the error happens. But you will need to configure the profiler to show the errors.
Within a web site I'm using the PrincipalPermission attribute to restrict access to certain methods.
Here's a canoncial example:
class Program
{
static void Main(string[] args)
{
Foo();
}
[System.Security.Permissions.PrincipalPermission(System.Security.Permissions.SecurityAction.Demand, Role = "Winners")]
static void Foo()
{ }
}
If the principal isn't in the role specified then the .net infrastructure throws a System.Security.SecurityException with the generic message "Request for principal permission failed".
If the permission check fails I'd like to log what role the PrincipalPermission required. This will be really useful for our support staff who can then either assign the role to the user and/or monitor the logs to see if anything suspicious is happening. Clearly for security purposes the end user will still see a generic unauthorised message. I've trawled through the SecurityException itself but it doesn't have the "Role" anywhere in it.
Is there anyway to get this information?
If your code is fully trusted, you can extract the required information by parsing the XML representation of the SecurityException's FirstPermissionThatFailed property. However, for your second purpose of detecting "suspicious" activity, it might be preferable to simply log the return value of the SecurityException's ToString() method. This will include both the details of the denied PrincipalPermission and the stack trace where the exception occurred. The context given by the stack trace is likely to be very useful, assuming that the support staff in question understand how to relate it to your application structure.
I have tried PhluffyFotos example on Azure SDK 1.2 and it works perfect. Today I have installed on another (clen) computer Azure SDK 1.3 and I have also want to try PhluffyFotos on it but it does not work. I have problem with this part:
if (!Roles.GetAllRoles().Contains("Administrator"))
{
Roles.CreateRole("Administrator");
}
It seems it somehow does not load the custom RoleProvider (TableStorageRoleProvider). Do you have any idea what it could be?
I get the following error: "The Role Manager feature has not been enabled.", because of the following exception "'System.Web.Security.Roles.ApplicationName' threw an exception of type 'System.Configuration.Provider.ProviderException'".
Can someone test this example and see what is the problem? http://phluffyfotos.codeplex.com/
Firsty I have the "SetConfigurationSettingPublisher" problem with this example, but I have successfully resole it.
EDIT:
I have look deeper into it and I am sure there are a problem with Role provider. Somehow the Roles class do not read config file. Have anyone any idea why?
I have the exact same problem with my own project. I verified with Fusion logs that the assembly which contains the custom providers dont even load. so it seems the problem is somehow related to the web.config settings being ignored.
To run PhluffyFotos example on Azure SKD 1.3 you have to the following:
Change reference Microsoft.WindowsAzure.StorageClient from 1.0 to 1.1
Move "GetConfigurationSettingValue" to the Global.asax "Application_Start" event.
Move Role related initialization to the Global.asax "Application_BeginRequest" event, but you have to ensure that it executes only once. Example:
private static object gate = new object();
private static bool initialized = false;
protected void Application_BeginRequest()
{
if (initialized)
{
return;
}
lock (gate)
{
if (!initialized)
{
// We need to check if this is the first launch of the app and pre-create
// the admin role and the first user to be admin (still needs to register).
if (!Roles.GetAllRoles().Contains("Administrator"))
{
Roles.CreateRole("Administrator");
}
if (!Roles.GetUsersInRole("Administrator").Any())
{
Roles.AddUserToRole(RoleEnvironment.GetConfigurationSettingValue("DefaultAdminRoleUser"), "Administrator");
}
initialized = true;
}
}
}
I posted a version of the code with the fixes suggested by Peter to rapidshare here:
http://rapidshare.com/files/434649379/PhluffyFotos.zip
For those who don't want to fuss around fixing the dependencies etc.
Cheers,
Daniel