DateTime Conversion error while using CodeFirst - entity-framework

I am using EF 6 Code First and creating a User and A Role and associating the user to the Role in Seed Method.
AppUserManager userManager = new AppUserManager(new UserStore<AppUser>(context));
AppRoleManager roleManager = new AppRoleManager(new RoleStore<AppRole>(context));
string roleName = "Administrators";
string userName = "Admin";
string password = "Admin#2016";
string email = "admin#admin.com";
if (roleManager.RoleExists(roleName))
{
roleManager.Create(new AppRole(roleName));
}
AppUser user = userManager.FindByName(userName);
if (user == null)
{
userManager.Create(new AppUser {UserName = userName, Email = email}, password);
user = userManager.FindByName(userName);
}
if (!userManager.IsInRole(user.Id, roleName))
userManager.AddToRole(user.Id, roleName);
But I am getting The conversion of a datetime2 data type to a datetime data type resulted in an out-of-range value.
The statement has been terminated error while executing the following statement.
userManager.Create(new AppUser {UserName = userName, Email = email}, password);
There is a field in IdentityUser base class called LockoutEndDateUtc it's type is DateTime? and in Database it is being correctly modeled as nullable.
I have seen other posts which instructs me to populate the date fields. But as it is nullable why should I populate it?
Yet I tried to initialize it like this:
LockoutEndDateUtc = DateTime.UtcNow.AddYears(3)
But still no luck.
I am not understanding why this error is popping up. Please help.
Thanks

Related

How to get FirstName/LastName using Keycloak UserRegistrationProvider?

I am looking for any way to get the firstname or the lastname of a new self-registered user on keyclock using a User Storage Provider ?
In my case, i'm working with Keycloak 12 and an old legacy MySQL database where I have to store all my users.
Implementing into my SPI the UserRegistrationProvider.addUser(RealmModel realm, String username) and the CredentialInputUpdater.updateCredential(RealmModel realm, UserModel user, CredentialInput input) allows me to catch the username and the password ... but I can't get any other basic information such as firstname/lastname ?
Here are my two implementation of CredentialInputUpdater and UserRegistrationProvider :
#Override
public UserModel addUser(final RealmModel realmModel, final String username) {
Integer id = userRepository.createUser(username, "password");
User user = null;
if (id != null) {
user = new User(id.toString(), username, "firstName", "userName", "password");
}
return user != null ? new UserAdapter(session, realmModel, model, user) : null;
}
#Override
public boolean updateCredential(RealmModel realm, UserModel user, CredentialInput input) {
if (!supportsCredentialType(input.getType()) || !(input instanceof UserCredentialModel)) {
return false;
}
UserCredentialModel cred = (UserCredentialModel) input;
return userRepository.updateCredentials(user.getUsername(), cred.getChallengeResponse());
}
Any idea on how to get these two data ?
A bit late for your question, but I ran into a similar problem. My use case was the following : I had to call an external API from the addUser method while providing both username and password.
After debugging Keycloak I found out you can retrieve every parameters filled in the form inside the Keycloak session (or the context).
Here is an example for the password :
String password = this.session.getContext()
.getContextObject(HttpRequest.class)
.getDecodedFormParameters()
.getFirst("password");
Hopefully, this will help other people.
After some days of research, I finally found the solution.
I'm not sure if it works on keycloak 12, but it does on keycloak 18.
This comment give me the point.
So in addUser you don't have to persit the new user, you only have to create your UserAdapter and just before return UserModel I added:
javax.enterprise.inject.spi.CDI.current().getBeanManager().fireEvent(userAdapter);
and in the same class I added the event listener:
public void observeUserAddedEvent(#Observes(during = TransactionPhase.BEFORE_COMPLETION) UserModel addedUser) {
// persist the "post populated" user
}

Getting user from DbContext after CreateAsync

I have a model called AppUser that inherits IdentityUser and I want to set some properties that exist only on AppUser. After creating the user via UserManager and getting the new Id I attempt to get the AppUser from DbContext however it is null and don't quite understand why.
How can I get the newly added AppUser?
...
var user = new IdentityUser { UserName = Input.Email, Email = Input.Email };
var result = await _userManager.CreateAsync(user);
var userId = await _userManager.GetUserIdAsync(user);
var appUser = _context.AppUsers.FirstOrDefault(x=>x.Id==userId); // <--- This is null

AspNetUserRoles not in EDMX when generating from database

I have did some searching around on this issue and have come across a few questions in regards to AspNetUserRoles not being in the EDMX designer when generating from the database. However its in the ModelBrowser and I can't get this table to show up so I can use Roles Authorization.
When I hit this method in my Roles class
public override string[] GetRolesForUser(string username)
{
DTE = new DatabaseTestingEntities();
string userID = DTE.AspNetUsers.Where(w => w.Email == username).Select(s => s.Id).FirstOrDefault();
string roleID = DTE.AspNetUsers.Include("AspNetRoles").Where(s => s.Id == userID).FirstOrDefault().ToString();//.AspNetUserRoles.Where(w => w.UserId == userID).Select(s => s.RoleId).FirstOrDefault();
string roleName = DTE.AspNetRoles.Where(w => w.Id == roleID).Select(s => s.Name).FirstOrDefault();
string[] results = { roleName };
return results;
}
The results always come back as null..
However it should look like this instead
public override string[] GetRolesForUser(string username)
{
DTE = new DatabaseTestingEntities();
string userID = DTE.AspNetUsers.Where(w => w.Email == username).Select(s => s.Id).FirstOrDefault();
string roleID = DTE.AspNetUserRoles.Where(w => w.UserId == userID).Select(s => s.RoleId).FirstOrDefault();
string roleName = DTE.AspNetRoles.Where(w => w.Id == roleID).Select(s => s.Name).FirstOrDefault();
string[] results = { roleName };
return results;
}
But that way throws an error because the AspNetUserRoles isn't in the EDMX designer when I generate the EF from the database.
How can I get this table to appear so I can continue on with what I need to do?
I have tried updating the EDMX and that doesn't work either.
I just had this question myself more or less... "Where is the AspNetUserRoles table in the model?"
My understanding is that the AspNetUserRoles table is created and consists of two foreign keys, one to the AspNetUsers table for it's Id value, and one to the AspNetRoles table, also for its Id value. When you assign a role to a user, it adds a row into the AspNetUserRoles table so as to give you what is called a "Navigation Property" on the AspNetUsers table. Look at your edmx and find the AspNetUsers table, at the bottom you'll see a Navigation Property of "AspNetRoles" and this collection is available to you in code on an AspNetUser object.
As a user can belong to many roles, this Navigation Property is a collection that can be assigned to a List something like this:
AspNetUser selectedUser = dbContext.AspNetUsers.FirstOrDefault(u => u.UserName == "foo");
if (selectedUser == null) return;
List<AspNetRole> selectedUsersRoles = selectedUser.AspNetRoles.ToList();
For the original poster's I would return the List and work with that...
public override List<AspNetRoles> GetRolesForUser(string username)
{
DTE = new DatabaseTestEntities();
AspNetUser selectedUser = DTE.AspNetUsers.FirstOrDefault(u => u.UserName == username);
if (selectedUser == null) return null; //User not found - return null
return List<AspNetRole> selectedUsersRoles = selectedUser.AspNetRoles.ToList();
}
This basically means you don't "need" the AspNetUserRoles table explicitly. You should be able to work with a user's roles as noted above. I'm not sure if it's recommended or not, but I would not directly insert into the AspNetUserRoles table either. You should just add a role to the user object and let the UserRoles table update automatically.

How to seed a user at initializer with Identity asp.net mvc 5?

While working with database initializer, I can save a role and a user at my development database, but the password never works. I can not login.
This is the code, what is it lacking?
public class DevelopmentDbInitializer : System.Data.Entity. DropCreateDatabaseIfModelChanges<ApplicationDbContext>
{
protected override void Seed(ApplicationDbContext context)
{
string password = "1_Changeme";
string administrator = "Administrator";
string adminEmail = "admin#office.com";
// Role
if (!context.Roles.Any(role => role.Name == Utils.Constants.ROLE_ADMINISTRATOR))
{
var roleStore = new RoleStore<IdentityRole>(context);
var roleManager = new RoleManager<IdentityRole>(roleStore);
var adminRole = new IdentityRole { Name = Utils.Constants.ROLE_ADMINISTRATOR };
roleManager.Create(adminRole);
}
// User
if (!context.Users.Any(user => user.UserName == administrator))
{
var userStore = new UserStore<ApplicationUser>(context);
var userManager = new UserManager<ApplicationUser>(userStore);
var adminUser = new ApplicationUser { Email = adminEmail, UserName = administrator, PhoneNumber = "7144251556" };
userManager.Create(adminUser, password);
userManager.AddToRole(adminUser.Id, Utils.Constants.ROLE_ADMINISTRATOR);
}
}
}
User is at database, but there is something with the password. I also use a variant with hasher and is the same story. This code seems to work on older versions of Visual Studio an Entity.
Anything changed last year with VS and its libraries?
Thanks in advance.
Using Visual Studio 2015. I suppose it is Identity 2.0. Code came from different places at stackoverflow...

Entity Framework Updating with Stub causes Primary Key Violation

I have the following common tables with the relationships setup in a many to many fashion in my entity model:
Users - UserCodePK, UserName
UserGroups - UserCodeFK,GroupCodeFK
Groups - GroupCodePK,GroupDescription
My Code when trying to add a user:
public static string CreateUser(User user)
{
using (var dbContext = new DCSEntities())
{
User u = new User
{
UserCodePK = "NewUser",
txtUserName = "New User Name
};
u.Groups.Add(new UserGroup {GroupCode = "ADMIN"});
u.Groups.Add(new UserGroup {GroupCode = "SUPER"});
dbContext.Users.AddObject(user);
dbContext.SaveChanges();
}
}
The error that I'm getting is :
"Violation of PRIMARY KEY constraint 'PK_Groups'. Cannot insert duplicate key in object 'dbo.Groups'. The duplicate key value is (ADMIN)"
Basically saying that I'm trying to add the group "ADMIN", which already exists in that table. I thought that by using the stub as above, that I won't need to go the database to fetch the "ADMIN" group and add it to the User object.
Any advice on how to get rid of the error?
EDIT: My Completed Code Based on the Suggestions Below(I hope this is in the right place?)
UI Method
protected void CreateUser()
{
User user = new User();
user.UserCodePK = txtUserCode.Text;
user.UserName = txtUserName.Text;
List<UserGroup> userGroups = new List<UserGroup>();
for (int i = 0; i < chkListGroups.Items.Count; i++)
{
if (chkListGroups.Items[i].Selected == true)
{
userGroups.Add(new UserGroup { GroupCodePK = chkListGroups.Items[i].Value });
}
}
string userCode = BLL.UserFunctions.CreateUser(user, userGroups);
}
BLL Method
public static string CreateUser(User user, List<UserGroup> userGroups)
{
return UserDAL.CreateUser(user,userGroups);
}
DAL Method
public static string CreateUser(User user,List<UserGroup> userGroups)
{
using (var dbContext = new DCSEntities())
{
foreach (UserGroup g in userGroups)
{
var ug = new UserGroup { GroupCode = g.GroupCode };
dbContext.UserGroups.Attach(ug);
user.UserGroups.Add(ug);
}
dbContext.Users.AddObject(user);
dbContext.SaveChanges();
return user.UserCode;
}
}
It's a good idea to work with stubs. You only have to make sure that EF won't see them as new object, which you can do by attaching the stub to the context. Now EF will not give it the status Added.
var adminGroup = new UserGroup {GroupCode = "ADMIN"};
db.Groups.Attach(adminGroup);
...
u.Groups.Add(group);
If GroupCode is the primary key, EF will know how to associate the objects.