tugberkugurlu / aspnet.identity.ravendb Goto Github PK
View Code? Open in Web Editor NEWFully asynchronous, new and sweet ASP.NET Identity implementation for RavenDB
License: MIT License
Fully asynchronous, new and sweet ASP.NET Identity implementation for RavenDB
License: MIT License
Would it not make sense to use virtual methods on the UserStore, this would let me modify some of the existing methods to my liking. For my existing database when logging in I don't want to lookup a user by key, i want to use an index and lookup by email.
I am attempting to ConfirmEmail. I have implemented Registration but when i confirm the email, I receive 'Cannot set the confirmation status of the e-mail because user doesn't have an e-mail as RavenUserEmail document.'
I then attempted to extend RavenUser by creating a new class that inherits from RavenUser. Within this class i have a property RavenUserEmail and create it when I create the RavenUser within the Registration. When i attempt to Confirm the email, I receive an error 'Cannot set the confirmation status of the e-mail because user doesn't have an e-mail.'
This is the code within my AccountController:
// GET: /Account/ConfirmEmail
[AllowAnonymous]
public async Task ConfirmEmail(string userId, string code)
{
var result = await UserManager.ConfirmEmailAsync(userId, code);
return View();
}
Currently its not possible to override any behavior inside those properties
In version 1.0, users were stored as ApplicationUsers/#
(i.e. ApplicationUsers/225
). I understand the need to move to /UserName
to ensure uniqueness, but instead of ApplicationUsers/UserName
, my user accounts under 2.0 are being saved as RavenUsers/UserName
(even though I do derive ApplicationUsers from RavenUsers to add my own custom properties).
I create users like this:
var user = new ApplicationUser(model.UserName) {
DateRegistered = DateTime.UtcNow,
DateLastConnected = DateTime.UtcNow
};
user.SetEmail(model.Email);
var result = await UserManager.CreateAsync(user, model.Password);
I just want to make sure this is how it will always remain even when 2.0 becomes stable... If so, I'll move all my user accounts to the new naming convention.
RavenUsers/{userName}
should be forced to be the document id.
If I update claims of a user and then call the UpdateAsync method, the user is not updated in the database. The UpdateAsync does not throw an exception and returns success. Any idea why the user is not updated?
In the 2.0 branch at least , using the RavenUserStore.User() method results in "System.NotSupportedException: You can't get a sync query from async session" because the session is async.
If roles are stored as claims this should be anyway implemented in the store, currently this method throws exception with message Store does not implement IUserRoleStore.
After updating to PRE6 I am getting this error now. I was using RavenDB build 3.3528 with PRE1 I think it was OK but I had issues with getting roles for a user.
Something that the ApplicationUser
could not be cast to Models.Person (my own model) Not even sure why it was saying that. But I read that RavenDB 2 to 3 had some breaking changes and it was likley to that. (Even though I was already on RavenDB 3)
I upgraded Identity to PRE6 and raven to 3.3690 (When I run the sample from tag PRE6 I get the same issues (I thought I did but it worked fine in the end) + optimistic concurrency is not set on AutoFac too, on the sample!)
I get this error now.
Method not found: 'System.Threading.Tasks.Task1<!!0> Raven.Client.IAsyncDocumentSession.LoadAsync(System.String).
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.MissingMethodException: Method not found: 'System.Threading.Tasks.Task`1<!!0> Raven.Client.IAsyncDocumentSession.LoadAsync(System.String)'.
Source Error:
Line 49: if (ModelState.IsValid)
Line 50: {
Line 51: var user = await UserManager.FindAsync(model.UserName, model.Password);
Line 52: if (user != null)
Line 53: {
It seems that the method RavenUserStore.FindAsync assumes an incorrect document structure, where RavenUserLogins are stored seperately from RavenUsers when in fact they are just an array property in the RavenUser document. The method does not find the user when the correct login provider and provider key are present. While it might not be the most effective approach, I got the method working by changing it to the following:
public async Task<TUser> FindAsync(UserLoginInfo login)
{
if (login == null) throw new ArgumentNullException("login");
string keyToLookFor = RavenUserLogin.GenerateKey(login.LoginProvider, login.ProviderKey);
return await _documentSession.Query<TUser>().Where(u => u.Logins.Any(l => l.Id == keyToLookFor)).SingleOrDefaultAsync();
}
This is what the user looks like in the database, after creating it with the standard code in the VS2013 web template:
{
"UserName": "MortenChristiansen",
"Email": null,
"PhoneNumber": null,
"PasswordHash": null,
"SecurityStamp": "...",
"IsLockoutEnabled": false,
"IsTwoFactorEnabled": false,
"AccessFailedCount": 0,
"LockoutEndDate": null,
"Claims": [],
"Logins": [
{
"Id": "RavenUserLogins/Google/https://www.google.com/accounts/o8/id?id=...",
"UserId": "Morten Christiansen",
"LoginProvider": "Google",
"ProviderKey": "https://www.google.com/accounts/o8/id?id=..."
}
]
}
Attribute should be added for
[JsonConstructor]
public RavenUserClaim(string claimType, string claimValue)
Here is the Exception when searching for user:
Unable to find a constructor to use for type AspNet.Identity.RavenDB.Entities.RavenUserClaim. A class should either have a default constructor, one constructor with arguments or a constructor marked with the JsonConstructor attribute. Path 'Claims[0].ClaimType'.
Also I need in my project importing of test data on application startup. I am reading JSON text file, deserializing to proper object and store it into RavenDB and can't deserialize it with same exception.
Here is how I am deserializing:
private static void Insert<T>(IDocumentSession session, string path)
{
var folder = new DirectoryInfo(path);
var files = folder.EnumerateFiles("*.json");
foreach (var fileInfo in files)
{
var c = File.ReadAllText(fileInfo.FullName);
var obj = JsonConvert.DeserializeObject<T>(c);
session.Store(obj);
}
}
Why is it not allowed to use a dash "-" in the username?
var user = new Models.ApplicationUser(userEmail);
var result = await UserManager.CreateAsync(user, password);
Exception
Creating user Failed. User name [email protected] is invalid, can only contain letters or digits.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.Web.HttpException: Creating user Failed. User [email protected] is invalid, can only contain letters or digits.
When I go into RavenDB management panel, I can change the Key manually to include the "-" and the username is just a string.
Has anybody got this working in the OWIN pipeline?
I'm trying to mimic the EF implementation, per owin request.
Unless theres a better way...
app.CreatePerOwinContext<AppUserIdentityDbContext>(AppUserIdentityDbContext.Create);
app.CreatePerOwinContext<AppUserManager>(AppUserManager.Create);
Where AppUserManager : UserManager
and
public static AppUserManager Create(IdentityFactoryOptions<AppUserManager> options, IOwinContext context)
{
return = new AppUserManager(new UserStore<AppUserIdentity>(context.Get<AppUserIdentityDbContext>()));
}
Related to #26. Have a look: http://ayende.com/blog/163170/building-async-unit-of-work-with-mvc-4
You probably haven't used or seen this code in a while, but I have the following issue:
I login with a user that has an "admin" role Claim
"Claims": [
{
"ClaimType": "http://schemas.microsoft.com/ws/2008/06/identity/claims/role",
"ClaimValue": "admin"
}
],
And everything works fine. But to try and test of the roles are properly set up, I change the ClaimValue
to "admin2" in de database. When logging in I would expect to get a 401 unauthorised
response, but instead I see that the user being fetched from the Document Store still has the old ClaimValue
of "admin".
Any ideas on why the user is not being refreshed?
I grabbed the source code and changed RavenUserStore
so that i opens a new IAsyncSession
every time FindByNameAsync
is called, and that does fetch the user data anew.
Just mentioning in case it helps you to point me in the right direction
any ideas why an exception is thrown when i go to create a user with the same username as an existing user? i was expecting the result object having the errors detailed out.
thanks!
In RavenUserStore, the method IncrementAccessFailedCountAsync is supposed to return the failed count but rather it always returns zero.
It should return this
return Task.FromResult(user.AccessFailedCount);
I'm running into concurrency issues using the 2.0.0x implementation. Depending on the the timing of each call to the UserManager, I receive the following error when trying to use more than 1 API call that incorporates the RavenDB session in a controller context:
Only a single concurrent async request is allowed per async client instance.
My understanding is that the RavenDb AsyncDocumentSession
only allows one async request at a time per instance of itself. This results in the above error being thrown, again depending on the timing, if more than one request is used per controller context.
Is there a way to avoid this? Do I need to wire up a new ApplicationUserManager
with a new AsyncDocumentSession
each time I make a API call to ApplicationUserManager
?
I upgraded to RavenDB 3 and updated to Identity PRE6
You suggest this
IDocumentStore documentStore = new DocumentStore
{
Url = "http://localhost:8080",
DefaultDatabase = "AspNetIdentity"
}.Initialize();
using (IAsyncDocumentSession session = documentStore.OpenAsyncSession())
{
session.Advanced.UseOptimisticConcurrency = true;
RavenUserStore ravenUserStore = new RavenUserStore(session);
UserManager userManager = new UserManager(ravenUserStore);
// UserManager<RavenUser> is ready to use!
}
But I am using AutoFAC and I get the error: Optimistic concurrency disabled 'IAsyncDocumentSession' instance is not supported be......
On this line. How Do I set what is needed?
builder.Register(c => new RavenUserStore<Models.ApplicationUser>(c.Resolve(), false)).As<IUserStore<Models.ApplicationUser>>().InstancePerHttpRequest();
So the setting is on this line in autofac
builder.Register(c => c.Resolve().OpenAsyncSession()).As().InstancePerHttpRequest();
But how can I set .Advanced.UseOptimisticConcurrency = true ?
When executing any query on UserManager.Users against RavenDB that is hosted as separate service System.NotSupportedException is thrown.
[NotSupportedException: You can't get a sync query from async session]
Raven.Client.Document.Async.AsyncDocumentSession.Raven.Client.Linq.IDocumentQueryGenerator.Query(String indexName, Boolean isMapReduce) in c:\Builds\RavenDB-Stable\Raven.Client.Lightweight\Document\Async\AsyncDocumentSession.cs:618
Raven.Client.Linq.RavenQueryProviderProcessor`1.GetLuceneQueryFor(Expression expression) in c:\Builds\RavenDB-Stable\Raven.Client.Lightweight\Linq\RavenQueryProviderProcessor.cs:1439
Raven.Client.Linq.RavenQueryProviderProcessor`1.Execute(Expression expression) in c:\Builds\RavenDB-Stable\Raven.Client.Lightweight\Linq\RavenQueryProviderProcessor.cs:1477
Raven.Client.Linq.RavenQueryInspector`1.GetEnumerator() in c:\Builds\RavenDB-Stable\Raven.Client.Lightweight\Linq\RavenQueryInspector.cs:105
I have been trying to get a user by their ID, using UserManager
, which is an email address.
For the sake of example [email protected]
I also have a Model.Person
, which I store in the same database as the RavenUsers, and the Key is also the same email.
When I create the user I use this code
var user = new Models.ApplicationUser(userName);
(UserName is the Email)
I have now eventually got got this working by using
var user2 = UserManager.FindByName("[email protected]");
The problem is when I use this
var user3 = UserManager.FindById("[email protected]");
I get an exception
Unable to cast object of type 'Models.Person' to type 'Models.ApplicationUser'.
I have been trying to work out what the problem is about 2 days now, on and off, but it seems when I use the FinByID
, RavenDB, or Identidy.Raven DB for some reason actually matches up with the Person Key in the database. I couldn't understand why I was getting this exception the whole time since I am just calling a method and not trying to cast any thing.
When I use
var user3 = UserManager.FindByEmail("[email protected]");
It reutrns NULL, even though in the database under ApplciationUsers, the Email is the same as UserName and the same as the Key.
Is this a Identity.RavenDB problem?
This project is pitching itself as a provider for supporting AspNet Identity 2.0 for Raven DB. Therefore it should be more comprehensive and support IUserRoleStore. I dont think it should tell people to write their apps to only use claims over roles.
Support both and let the users decide based on their needs / experience / preference.
var result = await UserManager.ChangePhoneNumberAsync(User.Identity.GetUserId(), model.PhoneNumber, model.Code);
This blows up with the following error:
Cannot set the confirmation status of the phone number because user doesn't have a phone number as RavenUserPhoneNumber document.
There are cases where we 'await' unnecessarily. Check and remove them.
Hi,
I think the functions FindAsync/CreateAsync in RavenUserStore are not stable. In my previous projects, I had a lot of troubles with stale data, even with static indexes. IMHO, a Raven "style" will be better. Let's treat RavenUserLogin as independent document
public class RavenUserLogin
{
const string KEY_TEMPLATE = "RavenUserLogin/{0}/{1}";
public RavenUserLogin()
{
}
public RavenUserLogin(UserLoginInfo loginInfo, string userId)
{
Id = GenerateKey(loginInfo);
UserId = userId;
}
public string Id { get; set; }
public string UserId { get; set; }
public static string GenerateKey(UserLoginInfo loginInfo)
{
return string.Format(KEY_TEMPLATE, loginInfo.LoginProvider, loginInfo.ProviderKey);
}
}
Then,
public async Task<TUser> FindAsync(UserLoginInfo login)
{
var lg = await DocumentSession
.Include<RavenUserLogin>(x=>x.UserId)
.LoadAsync<RavenUserLogin>(RavenUserLogin.GenerateKey(login));
return (lg != null) ? await DocumentSession.LoadAsync<TUser>(lg.UserId) : null;
}
Best, T.C
This's from IdentityStoreManager
's CreateLocalUser
method:
if (await this.Context.Users.Create(user) && await this.Context.Secrets.Create(new UserSecret(user.UserName, password)) && await this.Context.Logins.Add(new UserLogin(user.Id, this.LocalLoginProvider, user.UserName)))
{
await this.Context.SaveChanges();
result = true;
}
As seen here, there are no user changes persisted before setting the UserSecret
and UserLogin
here. With the current store implementations, such a behavior won't work as RavenUserSecretStore
and RavenUserLoginStore
relies on the existence of RavenUser
.
However, UserLogin
instance needs the user id which is not there yet. How does this even work?
In order to use UserManager.Users property store must implement interface IQueryableUserStore. Currently its not possible to build any admin panel for users using such provider.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.