Skip to content

Commit

Permalink
Merge pull request #55 from jbuedel/auto-save
Browse files Browse the repository at this point in the history
Autosave
  • Loading branch information
JudahGabriel authored Apr 24, 2024
2 parents 2acdd31 + ebd70d9 commit 73014ff
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 18 deletions.
11 changes: 10 additions & 1 deletion RavenDB.Identity/RavenDbIdentityOptions.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
using Raven.Client.Documents.Session;

namespace Raven.Identity
{
/// <summary>
Expand All @@ -12,6 +14,13 @@ public class RavenDbIdentityOptions
/// Indexes need to be deployed to server in order for static index queries to work.
/// </remarks>
/// <seealso cref="IdentityUserIndex{TUser}"/>
public bool UseStaticIndexes { get; set; }
public bool UseStaticIndexes { get; set; }

/// <summary>
/// If set, changes detected in <see cref="RoleStore{TRole}" /> and <see cref="UserStore{TUser,TRole}"/>
/// will be saved to Raven immediately (by calling <see cref="IAsyncDocumentSession.SaveChangesAsync"/>).
/// Leave false (the default) if you've implemented the save changes call in middleware.
/// </summary>
public bool AutoSaveChanges { get; set; }
}
}
35 changes: 18 additions & 17 deletions RavenDB.Identity/RoleStore.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Options;
using Raven.Client;
using System;
using System.Collections.Generic;
Expand Down Expand Up @@ -51,9 +52,11 @@ public class RoleStore<TRole> : RoleStore<TRole, IdentityRoleClaim>
/// Constructs a new instance of <see cref="RoleStore{TRole}"/>.
/// </summary>
/// <param name="context">The <see cref="IAsyncDocumentSession"/>.</param>
/// <param name="options"></param>
/// <param name="describer">The <see cref="IdentityErrorDescriber"/>.</param>
public RoleStore(IAsyncDocumentSession context, IdentityErrorDescriber? describer = null)
: base(context, describer)
public RoleStore(IAsyncDocumentSession context, IOptions<RavenDbIdentityOptions> options,
IdentityErrorDescriber? describer = null)
: base(context, options, describer)
{
}

Expand All @@ -80,14 +83,17 @@ public abstract class RoleStore<TRole, TRoleClaim> :
where TRole : IdentityRole<TRoleClaim>
where TRoleClaim : IdentityRoleClaim
{
private readonly IOptions<RavenDbIdentityOptions> options;
/// <summary>
/// Constructs a new instance of <see cref="RoleStore{TRole, TRoleClaim}"/>.
/// </summary>
/// <param name="context">The <see cref="IAsyncDocumentSession"/>.</param>
/// <param name="describer">The <see cref="IdentityErrorDescriber"/>.</param>
public RoleStore(IAsyncDocumentSession context, IdentityErrorDescriber? describer = null)
public RoleStore(IAsyncDocumentSession context, IOptions<RavenDbIdentityOptions> options,
IdentityErrorDescriber? describer = null)
{
AsyncSession = context ?? throw new ArgumentNullException(nameof(context));
this.options = options ?? throw new ArgumentNullException(nameof(options));
ErrorDescriber = describer ?? new IdentityErrorDescriber();
}

Expand All @@ -104,23 +110,18 @@ public RoleStore(IAsyncDocumentSession context, IdentityErrorDescriber? describe
/// </summary>
public IdentityErrorDescriber ErrorDescriber { get; set; }

/// <summary>
/// Gets or sets a flag indicating if changes should be persisted after CreateAsync, UpdateAsync and DeleteAsync are called.
/// </summary>
/// <value>
/// True if changes should be automatically persisted, otherwise false.
/// </value>
public bool AutoSaveChanges { get; set; } = true;

/// <summary>Saves the current store.</summary>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>The <see cref="Task"/> that represents the asynchronous operation.</returns>
/// <param name="cancellationToken">
/// The <see cref="CancellationToken" /> used to propagate notifications that the operation
/// should be canceled.
/// </param>
/// <returns>The <see cref="Task" /> that represents the asynchronous operation.</returns>
private async Task SaveChanges(CancellationToken cancellationToken)
{
if (AutoSaveChanges)
{
await AsyncSession.SaveChangesAsync(cancellationToken);
}
if (options.Value.AutoSaveChanges)
{
await AsyncSession.SaveChangesAsync(cancellationToken);
}
}

#region IQueryableRoleStore
Expand Down
16 changes: 16 additions & 0 deletions RavenDB.Identity/UserStore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,17 @@ public virtual void Dispose()

#endregion

#region AutoSaveChanges implementation

private async Task SaveChangesAsync()
{
if (options.Value.AutoSaveChanges)
{
await DbSession.SaveChangesAsync();
}
}

#endregion
#region IUserStore implementation

/// <inheritdoc />
Expand Down Expand Up @@ -208,6 +219,7 @@ public virtual async Task<IdentityResult> UpdateAsync(TUser user, CancellationTo
logger.LogTrace("User {UserId} did not have modified Email, saving normally", user.Id);

// Email didn't change, so no reservation to update. Just save the user data
await SaveChangesAsync();
return IdentityResult.Success;
}

Expand All @@ -226,6 +238,8 @@ public virtual async Task<IdentityResult> UpdateAsync(TUser user, CancellationTo
// See if the email change was only due to case sensitivity.
if (string.Equals(user.Email, oldEmail, StringComparison.InvariantCultureIgnoreCase))
{
// Save the other user data.
await SaveChangesAsync();
return IdentityResult.Success;
}

Expand All @@ -238,6 +252,8 @@ public virtual async Task<IdentityResult> UpdateAsync(TUser user, CancellationTo
}

await TryRemoveMigratedEmailReservation(oldEmail, user.Email);

await SaveChangesAsync();
return IdentityResult.Success;
}

Expand Down

0 comments on commit 73014ff

Please sign in to comment.