Implements IUserSecurityStore and ensures there is a security stamp token in place, have updated the repository layer to manual update this if ASPNet Identity APIs are not used to update users.
This commit is contained in:
@@ -2,11 +2,24 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Collections.Specialized;
|
||||
using System.Security.Claims;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.Identity;
|
||||
using Umbraco.Core.Security;
|
||||
|
||||
namespace Umbraco.Core.Models.Identity
|
||||
{
|
||||
public class BackOfficeIdentityUser : IdentityUser<int, IIdentityUserLogin, IdentityUserRole<string>, IdentityUserClaim<int>>
|
||||
{
|
||||
|
||||
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(BackOfficeUserManager manager)
|
||||
{
|
||||
// NOTE the authenticationType must match the umbraco one
|
||||
// defined in CookieAuthenticationOptions.AuthenticationType
|
||||
var userIdentity = await manager.CreateIdentityAsync(this, Constants.Security.BackOfficeAuthenticationType);
|
||||
return userIdentity;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets/sets the user's real name
|
||||
/// </summary>
|
||||
|
||||
@@ -38,5 +38,10 @@ namespace Umbraco.Core.Models.Membership
|
||||
/// Exposes the basic profile data
|
||||
/// </summary>
|
||||
IProfile ProfileData { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The security stamp used by ASP.Net identity
|
||||
/// </summary>
|
||||
string SecurityStamp { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -58,6 +58,7 @@ namespace Umbraco.Core.Models.Membership
|
||||
|
||||
private IUserType _userType;
|
||||
private string _name;
|
||||
private string _securityStamp;
|
||||
private List<string> _addedSections;
|
||||
private List<string> _removedSections;
|
||||
private ObservableCollection<string> _sectionCollection;
|
||||
@@ -76,6 +77,7 @@ namespace Umbraco.Core.Models.Membership
|
||||
|
||||
private bool _defaultToLiveEditing;
|
||||
|
||||
private static readonly PropertyInfo SecurityStampSelector = ExpressionHelper.GetPropertyInfo<User, string>(x => x.SecurityStamp);
|
||||
private static readonly PropertyInfo SessionTimeoutSelector = ExpressionHelper.GetPropertyInfo<User, int>(x => x.SessionTimeout);
|
||||
private static readonly PropertyInfo StartContentIdSelector = ExpressionHelper.GetPropertyInfo<User, int>(x => x.StartContentId);
|
||||
private static readonly PropertyInfo StartMediaIdSelector = ExpressionHelper.GetPropertyInfo<User, int>(x => x.StartMediaId);
|
||||
@@ -232,6 +234,22 @@ namespace Umbraco.Core.Models.Membership
|
||||
get { return new UserProfile(this); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The security stamp used by ASP.Net identity
|
||||
/// </summary>
|
||||
public string SecurityStamp
|
||||
{
|
||||
get { return _securityStamp; }
|
||||
set
|
||||
{
|
||||
SetPropertyValueAndDetectChanges(o =>
|
||||
{
|
||||
_securityStamp = value;
|
||||
return _securityStamp;
|
||||
}, _securityStamp, SecurityStampSelector);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used internally to check if we need to add a section in the repository to the db
|
||||
/// </summary>
|
||||
|
||||
@@ -51,6 +51,11 @@ namespace Umbraco.Core.Models.Rdbms
|
||||
[NullSetting(NullSetting = NullSettings.Null)]
|
||||
[Length(10)]
|
||||
public string UserLanguage { get; set; }
|
||||
|
||||
[Column("securityStampToken")]
|
||||
[NullSetting(NullSetting = NullSettings.Null)]
|
||||
[Length(255)]
|
||||
public string SecurityStampToken { get; set; }
|
||||
|
||||
[ResultColumn]
|
||||
public List<User2AppDto> User2AppDtos { get; set; }
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using Umbraco.Core.Models.Membership;
|
||||
@@ -32,7 +33,9 @@ namespace Umbraco.Core.Persistence.Factories
|
||||
IsLockedOut = dto.NoConsole,
|
||||
IsApproved = dto.Disabled == false,
|
||||
Email = dto.Email,
|
||||
Language = dto.UserLanguage
|
||||
Language = dto.UserLanguage,
|
||||
//make it a GUID if it's empty
|
||||
SecurityStamp = dto.SecurityStampToken.IsNullOrWhiteSpace() ? Guid.NewGuid().ToString() : dto.SecurityStampToken
|
||||
};
|
||||
|
||||
foreach (var app in dto.User2AppDtos)
|
||||
@@ -61,7 +64,8 @@ namespace Umbraco.Core.Persistence.Factories
|
||||
UserLanguage = entity.Language,
|
||||
UserName = entity.Name,
|
||||
Type = short.Parse(entity.UserType.Id.ToString(CultureInfo.InvariantCulture)),
|
||||
User2AppDtos = new List<User2AppDto>()
|
||||
User2AppDtos = new List<User2AppDto>(),
|
||||
SecurityStampToken = entity.SecurityStamp
|
||||
};
|
||||
|
||||
foreach (var app in entity.AllowedSections)
|
||||
|
||||
@@ -98,6 +98,12 @@ namespace Umbraco.Core.Persistence.Migrations.Initial
|
||||
return new Version(7, 0, 0);
|
||||
}
|
||||
|
||||
//if the error is for umbracoAccess it must be the previous version to 7.3 since that is when it is added
|
||||
if (Errors.Any(x => x.Item1.Equals("Table") && (x.Item2.InvariantEquals("umbracoAccess"))))
|
||||
{
|
||||
return new Version(7, 2, 5);
|
||||
}
|
||||
|
||||
return UmbracoVersion.Current;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
using System.Linq;
|
||||
using Umbraco.Core.Configuration;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenThreeZero
|
||||
{
|
||||
[Migration("7.3.0", 10, GlobalSettings.UmbracoMigrationName)]
|
||||
public class AddUserSecurityStampColumn : MigrationBase
|
||||
{
|
||||
public override void Up()
|
||||
{
|
||||
//Don't exeucte if the column is already there
|
||||
var columns = SqlSyntax.GetColumnsInSchema(Context.Database).ToArray();
|
||||
if (columns.Any(x => x.TableName.InvariantEquals("umbracoUser") && x.ColumnName.InvariantEquals("securityStampToken"))) return;
|
||||
|
||||
Create.Column("securityStampToken").OnTable("umbracoUser").AsString(255).Nullable();
|
||||
}
|
||||
|
||||
public override void Down()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -170,7 +170,8 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
{"userName", "Name"},
|
||||
{"userLogin", "Username"},
|
||||
{"userEmail", "Email"},
|
||||
{"userLanguage", "Language"}
|
||||
{"userLanguage", "Language"},
|
||||
{"securityStampToken", "SecurityStamp"}
|
||||
};
|
||||
|
||||
//create list of properties that have changed
|
||||
@@ -183,6 +184,15 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
if (dirtyEntity.IsPropertyDirty("RawPasswordValue") && entity.RawPasswordValue.IsNullOrWhiteSpace() == false)
|
||||
{
|
||||
changedCols.Add("userPassword");
|
||||
|
||||
//special case - when using ASP.Net identity the user manager will take care of updating the security stamp, however
|
||||
// when not using ASP.Net identity (i.e. old membership providers), we'll need to take care of updating this manually
|
||||
// so we can just detect if that property is dirty, if it's not we'll set it manually
|
||||
if (dirtyEntity.IsPropertyDirty("SecurityStamp") == false)
|
||||
{
|
||||
userDto.SecurityStampToken = entity.SecurityStamp = Guid.NewGuid().ToString();
|
||||
changedCols.Add("securityStampToken");
|
||||
}
|
||||
}
|
||||
|
||||
//only update the changed cols
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace Umbraco.Core.Security
|
||||
: base(store)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
#region What we support do not currently
|
||||
|
||||
//NOTE: Not sure if we really want/need to ever support this
|
||||
@@ -42,12 +42,6 @@ namespace Umbraco.Core.Security
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
//TODO: Support this
|
||||
public override bool SupportsUserSecurityStamp
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
//TODO: Support this
|
||||
public override bool SupportsUserTwoFactor
|
||||
{
|
||||
|
||||
@@ -16,20 +16,22 @@ namespace Umbraco.Core.Security
|
||||
IUserPasswordStore<BackOfficeIdentityUser, int>,
|
||||
IUserEmailStore<BackOfficeIdentityUser, int>,
|
||||
IUserLoginStore<BackOfficeIdentityUser, int>,
|
||||
IUserRoleStore<BackOfficeIdentityUser, int>
|
||||
IUserRoleStore<BackOfficeIdentityUser, int>,
|
||||
IUserSecurityStampStore<BackOfficeIdentityUser, int>
|
||||
|
||||
//TODO: This would require additional columns/tables for now people will need to implement this on their own
|
||||
//IUserPhoneNumberStore<BackOfficeIdentityUser, int>,
|
||||
//IUserTwoFactorStore<BackOfficeIdentityUser, int>,
|
||||
|
||||
//TODO: This will require additional columns/tables
|
||||
//IUserLockoutStore<BackOfficeIdentityUser, int>
|
||||
|
||||
//TODO: Implement this - might need to add a new column for this
|
||||
// http://stackoverflow.com/questions/19487322/what-is-asp-net-identitys-iusersecuritystampstoretuser-interface
|
||||
//IUserSecurityStampStore<BackOfficeIdentityUser, int>
|
||||
|
||||
//TODO: To do this we need to implement IQueryable - seems pretty overkill?
|
||||
//TODO: To do this we need to implement IQueryable - we'll have an IQuerable implementation soon with the UmbracoLinqPadDriver implementation
|
||||
//IQueryableUserStore<BackOfficeIdentityUser, int>
|
||||
{
|
||||
private readonly IUserService _userService;
|
||||
private readonly IExternalLoginService _externalLoginService;
|
||||
private bool _disposed = false;
|
||||
|
||||
public BackOfficeUserStore(IUserService userService, IExternalLoginService externalLoginService, MembershipProviderBase usersMembershipProvider)
|
||||
{
|
||||
@@ -53,6 +55,7 @@ namespace Umbraco.Core.Security
|
||||
/// </summary>
|
||||
protected override void DisposeResources()
|
||||
{
|
||||
_disposed = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -62,6 +65,7 @@ namespace Umbraco.Core.Security
|
||||
/// <returns/>
|
||||
public Task CreateAsync(BackOfficeIdentityUser user)
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
if (user == null) throw new ArgumentNullException("user");
|
||||
|
||||
var userType = _userService.GetUserTypeByAlias(
|
||||
@@ -108,6 +112,7 @@ namespace Umbraco.Core.Security
|
||||
/// <returns/>
|
||||
public async Task UpdateAsync(BackOfficeIdentityUser user)
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
if (user == null) throw new ArgumentNullException("user");
|
||||
|
||||
var asInt = user.Id.TryConvertTo<int>();
|
||||
@@ -139,6 +144,7 @@ namespace Umbraco.Core.Security
|
||||
/// <returns/>
|
||||
public Task DeleteAsync(BackOfficeIdentityUser user)
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
if (user == null) throw new ArgumentNullException("user");
|
||||
|
||||
var asInt = user.Id.TryConvertTo<int>();
|
||||
@@ -164,6 +170,7 @@ namespace Umbraco.Core.Security
|
||||
/// <returns/>
|
||||
public Task<BackOfficeIdentityUser> FindByIdAsync(int userId)
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
var user = _userService.GetUserById(userId);
|
||||
if (user == null)
|
||||
{
|
||||
@@ -179,6 +186,7 @@ namespace Umbraco.Core.Security
|
||||
/// <returns/>
|
||||
public Task<BackOfficeIdentityUser> FindByNameAsync(string userName)
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
var user = _userService.GetByUsername(userName);
|
||||
if (user == null)
|
||||
{
|
||||
@@ -197,6 +205,7 @@ namespace Umbraco.Core.Security
|
||||
/// <returns/>
|
||||
public Task SetPasswordHashAsync(BackOfficeIdentityUser user, string passwordHash)
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
if (user == null) throw new ArgumentNullException("user");
|
||||
if (passwordHash.IsNullOrWhiteSpace()) throw new ArgumentNullException("passwordHash");
|
||||
|
||||
@@ -212,6 +221,7 @@ namespace Umbraco.Core.Security
|
||||
/// <returns/>
|
||||
public Task<string> GetPasswordHashAsync(BackOfficeIdentityUser user)
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
if (user == null) throw new ArgumentNullException("user");
|
||||
|
||||
return Task.FromResult(user.PasswordHash);
|
||||
@@ -224,6 +234,7 @@ namespace Umbraco.Core.Security
|
||||
/// <returns/>
|
||||
public Task<bool> HasPasswordAsync(BackOfficeIdentityUser user)
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
if (user == null) throw new ArgumentNullException("user");
|
||||
|
||||
return Task.FromResult(user.PasswordHash.IsNullOrWhiteSpace() == false);
|
||||
@@ -236,6 +247,7 @@ namespace Umbraco.Core.Security
|
||||
/// <returns/>
|
||||
public Task SetEmailAsync(BackOfficeIdentityUser user, string email)
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
if (user == null) throw new ArgumentNullException("user");
|
||||
if (email.IsNullOrWhiteSpace()) throw new ArgumentNullException("email");
|
||||
|
||||
@@ -251,6 +263,7 @@ namespace Umbraco.Core.Security
|
||||
/// <returns/>
|
||||
public Task<string> GetEmailAsync(BackOfficeIdentityUser user)
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
if (user == null) throw new ArgumentNullException("user");
|
||||
|
||||
return Task.FromResult(user.Email);
|
||||
@@ -263,6 +276,7 @@ namespace Umbraco.Core.Security
|
||||
/// <returns/>
|
||||
public Task<bool> GetEmailConfirmedAsync(BackOfficeIdentityUser user)
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
@@ -273,6 +287,7 @@ namespace Umbraco.Core.Security
|
||||
/// <returns/>
|
||||
public Task SetEmailConfirmedAsync(BackOfficeIdentityUser user, bool confirmed)
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
@@ -283,6 +298,7 @@ namespace Umbraco.Core.Security
|
||||
/// <returns/>
|
||||
public Task<BackOfficeIdentityUser> FindByEmailAsync(string email)
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
var user = _userService.GetByEmail(email);
|
||||
var result = user == null
|
||||
? null
|
||||
@@ -298,6 +314,7 @@ namespace Umbraco.Core.Security
|
||||
/// <returns/>
|
||||
public Task AddLoginAsync(BackOfficeIdentityUser user, UserLoginInfo login)
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
if (user == null) throw new ArgumentNullException("user");
|
||||
if (login == null) throw new ArgumentNullException("login");
|
||||
|
||||
@@ -316,6 +333,7 @@ namespace Umbraco.Core.Security
|
||||
/// <returns/>
|
||||
public Task RemoveLoginAsync(BackOfficeIdentityUser user, UserLoginInfo login)
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
if (user == null) throw new ArgumentNullException("user");
|
||||
if (login == null) throw new ArgumentNullException("login");
|
||||
|
||||
@@ -335,6 +353,7 @@ namespace Umbraco.Core.Security
|
||||
/// <returns/>
|
||||
public Task<IList<UserLoginInfo>> GetLoginsAsync(BackOfficeIdentityUser user)
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
if (user == null) throw new ArgumentNullException("user");
|
||||
return Task.FromResult((IList<UserLoginInfo>)
|
||||
user.Logins.Select(l => new UserLoginInfo(l.LoginProvider, l.ProviderKey)).ToList());
|
||||
@@ -345,7 +364,10 @@ namespace Umbraco.Core.Security
|
||||
/// </summary>
|
||||
/// <returns/>
|
||||
public Task<BackOfficeIdentityUser> FindAsync(UserLoginInfo login)
|
||||
{
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
if (login == null) throw new ArgumentNullException("login");
|
||||
|
||||
//get all logins associated with the login id
|
||||
var result = _externalLoginService.Find(login).ToArray();
|
||||
if (result.Any())
|
||||
@@ -363,6 +385,117 @@ namespace Umbraco.Core.Security
|
||||
return Task.FromResult<BackOfficeIdentityUser>(null);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Adds a user to a role (section)
|
||||
/// </summary>
|
||||
/// <param name="user"/><param name="roleName"/>
|
||||
/// <returns/>
|
||||
public Task AddToRoleAsync(BackOfficeIdentityUser user, string roleName)
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
if (user == null) throw new ArgumentNullException("user");
|
||||
|
||||
if (user.AllowedSections.InvariantContains(roleName)) return Task.FromResult(0);
|
||||
|
||||
var asInt = user.Id.TryConvertTo<int>();
|
||||
if (asInt == false)
|
||||
{
|
||||
throw new InvalidOperationException("The user id must be an integer to work with the Umbraco");
|
||||
}
|
||||
|
||||
var found = _userService.GetUserById(asInt.Result);
|
||||
|
||||
if (found != null)
|
||||
{
|
||||
found.AddAllowedSection(roleName);
|
||||
}
|
||||
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes the role (allowed section) for the user
|
||||
/// </summary>
|
||||
/// <param name="user"/><param name="roleName"/>
|
||||
/// <returns/>
|
||||
public Task RemoveFromRoleAsync(BackOfficeIdentityUser user, string roleName)
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
if (user == null) throw new ArgumentNullException("user");
|
||||
|
||||
if (user.AllowedSections.InvariantContains(roleName) == false) return Task.FromResult(0);
|
||||
|
||||
var asInt = user.Id.TryConvertTo<int>();
|
||||
if (asInt == false)
|
||||
{
|
||||
throw new InvalidOperationException("The user id must be an integer to work with the Umbraco");
|
||||
}
|
||||
|
||||
var found = _userService.GetUserById(asInt.Result);
|
||||
|
||||
if (found != null)
|
||||
{
|
||||
found.RemoveAllowedSection(roleName);
|
||||
}
|
||||
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the roles for this user
|
||||
/// </summary>
|
||||
/// <param name="user"/>
|
||||
/// <returns/>
|
||||
public Task<IList<string>> GetRolesAsync(BackOfficeIdentityUser user)
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
if (user == null) throw new ArgumentNullException("user");
|
||||
return Task.FromResult((IList<string>)user.AllowedSections.ToList());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if a user is in the role
|
||||
/// </summary>
|
||||
/// <param name="user"/><param name="roleName"/>
|
||||
/// <returns/>
|
||||
public Task<bool> IsInRoleAsync(BackOfficeIdentityUser user, string roleName)
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
if (user == null) throw new ArgumentNullException("user");
|
||||
return Task.FromResult(user.AllowedSections.InvariantContains(roleName));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the security stamp for the user
|
||||
/// </summary>
|
||||
/// <param name="user"/><param name="stamp"/>
|
||||
/// <returns/>
|
||||
public Task SetSecurityStampAsync(BackOfficeIdentityUser user, string stamp)
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
if (user == null) throw new ArgumentNullException("user");
|
||||
|
||||
user.SecurityStamp = stamp;
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the user security stamp
|
||||
/// </summary>
|
||||
/// <param name="user"/>
|
||||
/// <returns/>
|
||||
public Task<string> GetSecurityStampAsync(BackOfficeIdentityUser user)
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
if (user == null) throw new ArgumentNullException("user");
|
||||
|
||||
//the stamp cannot be null, so if it is currently null then we'll just return a hash of the password
|
||||
return Task.FromResult(user.SecurityStamp.IsNullOrWhiteSpace()
|
||||
? user.PasswordHash.ToMd5()
|
||||
: user.SecurityStamp);
|
||||
}
|
||||
|
||||
private BackOfficeIdentityUser AssignLoginsCallback(BackOfficeIdentityUser user)
|
||||
{
|
||||
if (user != null)
|
||||
@@ -424,6 +557,11 @@ namespace Umbraco.Core.Security
|
||||
anythingChanged = true;
|
||||
user.StartContentId = identityUser.StartContentId;
|
||||
}
|
||||
if (user.SecurityStamp != identityUser.SecurityStamp)
|
||||
{
|
||||
anythingChanged = true;
|
||||
user.SecurityStamp = identityUser.SecurityStamp;
|
||||
}
|
||||
if (user.AllowedSections.ContainsAll(identityUser.AllowedSections) == false
|
||||
|| identityUser.AllowedSections.ContainsAll(user.AllowedSections) == false)
|
||||
{
|
||||
@@ -441,76 +579,10 @@ namespace Umbraco.Core.Security
|
||||
return anythingChanged;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a user to a role (section)
|
||||
/// </summary>
|
||||
/// <param name="user"/><param name="roleName"/>
|
||||
/// <returns/>
|
||||
public Task AddToRoleAsync(BackOfficeIdentityUser user, string roleName)
|
||||
private void ThrowIfDisposed()
|
||||
{
|
||||
if (user.AllowedSections.InvariantContains(roleName)) return Task.FromResult(0);
|
||||
|
||||
var asInt = user.Id.TryConvertTo<int>();
|
||||
if (asInt == false)
|
||||
{
|
||||
throw new InvalidOperationException("The user id must be an integer to work with the Umbraco");
|
||||
}
|
||||
|
||||
var found = _userService.GetUserById(asInt.Result);
|
||||
|
||||
if (found != null)
|
||||
{
|
||||
found.AddAllowedSection(roleName);
|
||||
_userService.Save(found);
|
||||
}
|
||||
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes the role (allowed section) for the user
|
||||
/// </summary>
|
||||
/// <param name="user"/><param name="roleName"/>
|
||||
/// <returns/>
|
||||
public Task RemoveFromRoleAsync(BackOfficeIdentityUser user, string roleName)
|
||||
{
|
||||
if (user.AllowedSections.InvariantContains(roleName) == false) return Task.FromResult(0);
|
||||
|
||||
var asInt = user.Id.TryConvertTo<int>();
|
||||
if (asInt == false)
|
||||
{
|
||||
throw new InvalidOperationException("The user id must be an integer to work with the Umbraco");
|
||||
}
|
||||
|
||||
var found = _userService.GetUserById(asInt.Result);
|
||||
|
||||
if (found != null)
|
||||
{
|
||||
found.RemoveAllowedSection(roleName);
|
||||
_userService.Save(found);
|
||||
}
|
||||
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the roles for this user
|
||||
/// </summary>
|
||||
/// <param name="user"/>
|
||||
/// <returns/>
|
||||
public Task<IList<string>> GetRolesAsync(BackOfficeIdentityUser user)
|
||||
{
|
||||
return Task.FromResult((IList<string>)user.AllowedSections.ToList());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if a user is in the role
|
||||
/// </summary>
|
||||
/// <param name="user"/><param name="roleName"/>
|
||||
/// <returns/>
|
||||
public Task<bool> IsInRoleAsync(BackOfficeIdentityUser user, string roleName)
|
||||
{
|
||||
return Task.FromResult(user.AllowedSections.InvariantContains(roleName));
|
||||
if (_disposed)
|
||||
throw new ObjectDisposedException(GetType().Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -381,6 +381,7 @@
|
||||
<Compile Include="Persistence\Mappers\DomainMapper.cs" />
|
||||
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenThreeZero\AddExternalLoginsTable.cs" />
|
||||
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenThreeZero\AddPublicAccessTables.cs" />
|
||||
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenThreeZero\AddUserSecurityStampColumn.cs" />
|
||||
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenThreeZero\MovePublicAccessXmlDataToDb.cs" />
|
||||
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenThreeZero\RemoveHelpTextColumn.cs" />
|
||||
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenThreeZero\RemoveLanguageLocaleColumn.cs" />
|
||||
|
||||
@@ -30,6 +30,7 @@ using umbraco.providers;
|
||||
using Microsoft.AspNet.Identity.Owin;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Umbraco.Core.Models.Identity;
|
||||
using IUser = Umbraco.Core.Models.Membership.IUser;
|
||||
|
||||
namespace Umbraco.Web.Editors
|
||||
{
|
||||
@@ -146,7 +147,7 @@ namespace Umbraco.Web.Editors
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[SetAngularAntiForgeryTokens]
|
||||
public HttpResponseMessage PostLogin(LoginModel loginModel)
|
||||
public async Task<HttpResponseMessage> PostLogin(LoginModel loginModel)
|
||||
{
|
||||
if (UmbracoContext.Security.ValidateBackOfficeCredentials(loginModel.Username, loginModel.Password))
|
||||
{
|
||||
@@ -161,6 +162,10 @@ namespace Umbraco.Web.Editors
|
||||
// we cannot mix HttpContext.Response.Cookies and the way WebApi/Owin work)
|
||||
var ticket = response.UmbracoLoginWebApi(user);
|
||||
|
||||
//Identity does some of it's own checks as well so we need to use it's sign in process too... this will essentially re-create the
|
||||
// ticket/cookie above but we need to create the ticket now so we can assign the Current Thread User/IPrinciple below
|
||||
await SignInAsync(Mapper.Map<IUser, BackOfficeIdentityUser>(user), isPersistent: true);
|
||||
|
||||
var http = this.TryGetHttpContext();
|
||||
if (http.Success == false)
|
||||
{
|
||||
@@ -211,15 +216,8 @@ namespace Umbraco.Web.Editors
|
||||
|
||||
owinContext.Authentication.SignIn(
|
||||
new AuthenticationProperties() { IsPersistent = isPersistent },
|
||||
await GenerateUserIdentityAsync(user));
|
||||
await user.GenerateUserIdentityAsync(UserManager));
|
||||
}
|
||||
|
||||
private async Task<ClaimsIdentity> GenerateUserIdentityAsync(BackOfficeIdentityUser user)
|
||||
{
|
||||
// NOTE the authenticationType must match the umbraco one
|
||||
// defined in CookieAuthenticationOptions.AuthenticationType
|
||||
var userIdentity = await UserManager.CreateIdentityAsync(user, global::Umbraco.Core.Constants.Security.BackOfficeAuthenticationType);
|
||||
return userIdentity;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -493,23 +493,14 @@ namespace Umbraco.Web.Editors
|
||||
OwinContext.Authentication.SignOut(Core.Constants.Security.BackOfficeExternalAuthenticationType);
|
||||
|
||||
OwinContext.Authentication.SignIn(
|
||||
new AuthenticationProperties() {IsPersistent = isPersistent},
|
||||
await GenerateUserIdentityAsync(user));
|
||||
}
|
||||
|
||||
private async Task<ClaimsIdentity> GenerateUserIdentityAsync(BackOfficeIdentityUser user)
|
||||
{
|
||||
// NOTE the authenticationType must match the umbraco one
|
||||
// defined in CookieAuthenticationOptions.AuthenticationType
|
||||
var userIdentity = await UserManager.CreateIdentityAsync(user, global::Umbraco.Core.Constants.Security.BackOfficeAuthenticationType);
|
||||
return userIdentity;
|
||||
new AuthenticationProperties() {IsPersistent = isPersistent},
|
||||
await user.GenerateUserIdentityAsync(UserManager));
|
||||
}
|
||||
|
||||
private IAuthenticationManager AuthenticationManager
|
||||
{
|
||||
get { return OwinContext.Authentication; }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the server variables regarding the application state
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Web;
|
||||
using Microsoft.AspNet.Identity;
|
||||
using Microsoft.AspNet.Identity.Owin;
|
||||
using Microsoft.Owin;
|
||||
using Microsoft.Owin.Extensions;
|
||||
using Microsoft.Owin.Security;
|
||||
@@ -11,6 +13,7 @@ using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Models.Identity;
|
||||
using Umbraco.Core.Security;
|
||||
using Constants = Umbraco.Core.Constants;
|
||||
|
||||
namespace Umbraco.Web.Security.Identity
|
||||
{
|
||||
@@ -84,16 +87,14 @@ namespace Umbraco.Web.Security.Identity
|
||||
{
|
||||
Provider = new CookieAuthenticationProvider
|
||||
{
|
||||
//TODO: Need to implement IUserSecurityStampStore on BackOfficeUserStore!
|
||||
|
||||
//// Enables the application to validate the security stamp when the user
|
||||
//// logs in. This is a security feature which is used when you
|
||||
//// change a password or add an external login to your account.
|
||||
//OnValidateIdentity = SecurityStampValidator
|
||||
// .OnValidateIdentity<UmbracoMembersUserManager<UmbracoApplicationUser>, UmbracoApplicationUser, int>(
|
||||
// TimeSpan.FromMinutes(30),
|
||||
// (manager, user) => user.GenerateUserIdentityAsync(manager),
|
||||
// identity => identity.GetUserId<int>())
|
||||
// Enables the application to validate the security stamp when the user
|
||||
// logs in. This is a security feature which is used when you
|
||||
// change a password or add an external login to your account.
|
||||
OnValidateIdentity = SecurityStampValidator
|
||||
.OnValidateIdentity<BackOfficeUserManager, BackOfficeIdentityUser, int>(
|
||||
TimeSpan.FromMinutes(30),
|
||||
(manager, user) => user.GenerateUserIdentityAsync(manager),
|
||||
identity => identity.GetUserId<int>())
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user