UserManager in Asp.Net Identity 2 prevents creation user with duplicate username through additional request to database to find possible duplicate. I think this is error prone and can cause concurrency errors. The correct mechanism should rely on on unique constraints or indexes. Am I wrong and do I miss something?
Links to source:
CreateAsync and ValidateUserName
No, you are not wrong. And Identity adds the unique index on Username column:
And the migration code for this table is:
CreateTable(
"dbo.AspNetUsers",
c => new
{
Id = c.String(nullable: false, maxLength: 128),
/* .... SNIP .... */
UserName = c.String(nullable: false, maxLength: 256),
})
.PrimaryKey(t => t.Id)
.Index(t => t.UserName, unique: true, name: "UserNameIndex");
Unique index is clearly set on the column.
p.s. you are looking on Identity v3 - it is not released. Current Identity v2.1 is not open source yet.
Related
I have an EntityType field:
->add('topic', null, [
'required' => false,
'class' => Category::class
])
And for new Category 's my js tool creates a new select option marked with __new_option__:
So the value to read is not the value. It is the label.
How can I read this value after submission.
I tried addViewTransformer, addEventListener with preSetData and postSetData.
But when I get the value - it shows everytime just __new_option__ but not the value to persist into the database.
Is there a way to do that?
How can I read this value after submission. I tried
addViewTransformer, addEventListener with preSetData and postSetData.
By reason of the post-data containing the topic-field eq 'new_option'. "It doesn't know anything about the selected value`s label".
I don`t know your implementation, but -> just change-modify the js-behaviour on submitting like:
let topicSelection = document.getElementById('SELECTOR');
topicSelection.options[el.selectedIndex].value = topicSelection.options[el.selectedIndex].innerHTML;
//... submitting
Though it has been set to on-delete: "ReferentialAction.Restrict" on foreign key "FK_TeamMember_Teams_TeamId", it gives the following error when trying to delete a record from TeamMember table. Can you please help me with how I should get rid of this error?
Microsoft.EntityFrameworkCore.DbUpdateException: An error occurred while updating the entries.
See the inner exception for details.
---> Microsoft.Data.SqlClient.SqlException (0x80131904): The DELETE statement conflicted with the
REFERENCE constraint "FK_TeamMember_Teams_TeamId". The conflict occurred in database "mot", table
"dbo.TeamMember", column 'TeamId'. The statement has been terminated.
Following is the migration code block
migrationBuilder.CreateTable(
name: "TeamMember",
columns: table => new
{
Id = table.Column<Guid>(nullable: false),
MarketingOfficerId = table.Column<Guid>(nullable: false),
TeamId = table.Column<Guid>(nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_TeamMember", x => x.Id);
table.ForeignKey(
name: "FK_TeamMember_Employees_MarketingOfficerId",
column: x => x.MarketingOfficerId,
principalTable: "Employees",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_TeamMember_Teams_TeamId",
column: x => x.TeamId,
principalTable: "Teams",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
});
OnModelCreating method I have used the following as well.
modelBuilder.Entity<Team>()
.HasMany(i => i.TeamMembers)
.WithOne(i=>i.Team)
.OnDelete(DeleteBehavior.Restrict);
Thank You
I think the behavior is correct since when the master table deletes a record it should delete its related records in the detail table. No point in keeping it. Data will be redundant. But in case if we want to make such a scenario, though we set CascadeDelete to Restrict within the migration.cs it will not work as expected. The following article will help with understanding the behaviours.
https://learn.microsoft.com/en-us/ef/core/saving/cascade-delete
I work on a ASP.NET Web API and have added support for GraphQL requests with GraphQL for .NET .
My queries are working as expected but I am now struggling to use the same logic with the mutations.
I have the following logic for my queries:
Field<ContactType>("contact", "This field returns the contact by Id",
arguments: new QueryArguments(QA_ContactId),
resolve: ctx => ContactResolvers.ContactDetails(ctx));
My resolver returns a ContactDomainEntity that is then resolved into a ContactType:
public class ContactType : ObjectGraphType<ContactDomainEntity>
{
public ContactType()
{
Name = "Contact";
Description = "Contact Type";
Field(c => c.Id);
Field(c => c.FirstName, nullable: true);
Field<ListGraphType<AddressType>, IEnumerable<AddressDTO>>(Field_Addresses)
.Description("Contact's addresses")
.Resolve(ctx => LocationResolvers.ResolveAddresses(ctx));
}
}
It all works really well and the address list is resolved with its own reslver (LocationResolvers.ResolveAddresses) which makes it reusable and helps with the separation of concerns.
Now I want to be able to edit a contact and was hoping to use the same logic where child-objects (like the list of addresses) would be handled by their own resolver. So I have created the following mutation:
Field<ContactType>("UpdateContact", "This field updates the Contact's details",
arguments: new QueryArguments(QA_Input<Types.Input.ContactInputType>()),
resolve: ctx => ContactResolvers.UpdateContact(ctx));
with the ContactInputType:
public class ContactInputType : InputObjectGraphType<ContactInputDTO>
{
public ContactInputType()
{
Name = "UpdateContactInput";
Description = "Update an existing contact";
Field(c => c.Id);
Field(c => c.FirstName, nullable: true);
Field<ListGraphType<AddressInputType>, IEnumerable<AddressDTO>>("Addresses")
.Description("Manage contact's addresses")
.Resolve(ctx => LocationResolvers.ManageAddresses(ctx));
}
}
(Note that I use DTOs to map the fields into an object which makes sense in my case but that is not related to my problem)
My issue is that only the resolver 'ContactResolvers.UpdateContact' gets called. The field resolver 'LocationResolvers.ManageAddresses' is never hit. If I replace the addresses field with the following:
Field(c => c.Addresses, nullable: true, type: typeof(ListGraphType<AddressInputType>));
my ContactInputDTO is correctly populated (i.e. its property 'Addresses' contains the right data) but it means I lose control on how the object properties are mapped and have to rely on them having the same name and cannot add additional logic that my resolver might have.
tl;dr How to use a field resolver with InputObjectGraphType? It works fine when returning an ObjectGraphType but I can't get it working on the receiving end.
I'm trying to rename my Identity 2.0 tables to have my app name before them. So I've overridden OnModelCreating:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<IdentityUser>().ToTable("appname_Users");
modelBuilder.Entity<IdentityRole>().ToTable("appname_Roles");
modelBuilder.Entity<IdentityUserClaim>().ToTable("appname_UserClaims");
modelBuilder.Entity<IdentityUserLogin>().ToTable("appname_UserLogins");
modelBuilder.Entity<IdentityUserRole>().ToTable("appname_UserRoles");
}
I deleted the Migrations folder, made sure these tables did not exist, and ran:
enable-migrations -Force
update-database
When I try to login to the site, it still says it can't find dbo.AspNetUsers.
When I check the migration script, I do see the following:
CreateTable(
"dbo.AspNetUsers",
c => new
{
Id = c.String(nullable: false, maxLength: 128),
})
.PrimaryKey(t => t.Id)
.ForeignKey("dbo.appname_Users", t => t.Id)
.Index(t => t.Id);
Where is it even getting the idea that it needs AspNetUsers? I've scoured documentation and can't find out what's going on. Any help would be appreciated.
Delete all your identity tables from database manually. Then in onModelCreating insert
modelBuilder.Entity<ApplicationUser>().ToTable("appname_Users");
modelBuilder.Entity<IdentityUserRole>().ToTable("appname_UserRoles");
modelBuilder.Entity<IdentityUserLogin>().ToTable("appname_UserLogins");
modelBuilder.Entity<IdentityUserClaim>().ToTable("appname_UserClaims");
modelBuilder.Entity<IdentityRole>().ToTable("appname_Roles");
if you create custom identity classes then use
modelBuilder.Entity<ApplicationUser>().ToTable("appname_Users");
modelBuilder.Entity<ApplicationRole>().HasKey<string>(r => r.Id).ToTable("appname_Roles");
modelBuilder.Entity<ApplicationUser>().HasMany<ApplicationUserRole>((ApplicationUser u) => u.UserRoles);
modelBuilder.Entity<ApplicationUserRole>().HasKey(r => new { UserId = r.UserId, RoleId = r.RoleId }).ToTable("appname_UserRoles");
This way works for me.........
given a user:
id, name, password
so I want to modify him, and set a name to it. But then if I persists, his password will be rewritten (set to empty), even though I didnt set it. But here is the nullable=true annotation! Right now it seems to work - but this way its impossible to persist if I want to set it null itself. Then how?
in the password field in form add the argument mapped => false do the Doctrine will not be considered as an entity field in the moment of form validation.
->add('password', 'password', array(
'mapped' => false
))