Merge branch '7.0.0' of https://github.com/umbraco/Umbraco-CMS into 7.0.0
This commit is contained in:
@@ -99,6 +99,10 @@ namespace Umbraco.Core
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static class Member
|
public static class Member
|
||||||
{
|
{
|
||||||
|
public static readonly string UmbracoMemberProviderName = "UmbracoMembershipProvider";
|
||||||
|
|
||||||
|
public static readonly string UmbracoRoleProviderName = "UmbracoRoleProvider";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Property alias for a Members Password Question
|
/// Property alias for a Members Password Question
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -411,6 +411,11 @@ namespace Umbraco.Core
|
|||||||
/// Alias for the XPath DropDownList datatype.
|
/// Alias for the XPath DropDownList datatype.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public const string XPathDropDownListAlias = "Umbraco.XPathDropDownList";
|
public const string XPathDropDownListAlias = "Umbraco.XPathDropDownList";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Alias for the email address property editor
|
||||||
|
/// </summary>
|
||||||
|
public const string EmailAddressAlias = "Umbraco.EmailAddress";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -20,6 +20,17 @@ namespace Umbraco.Core.Models
|
|||||||
private object _providerUserKey;
|
private object _providerUserKey;
|
||||||
private Type _userTypeKey;
|
private Type _userTypeKey;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor for creating a Member object
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="name">Name of the content</param>
|
||||||
|
/// <param name="contentType">ContentType for the current Content object</param>
|
||||||
|
public Member(string name, IMemberType contentType)
|
||||||
|
: base(name, -1, contentType, new PropertyCollection())
|
||||||
|
{
|
||||||
|
_contentType = contentType;
|
||||||
|
}
|
||||||
|
|
||||||
public Member(string name, string email, string username, string password, int parentId, IMemberType contentType)
|
public Member(string name, string email, string username, string password, int parentId, IMemberType contentType)
|
||||||
: base(name, parentId, contentType, new PropertyCollection())
|
: base(name, parentId, contentType, new PropertyCollection())
|
||||||
{
|
{
|
||||||
@@ -427,7 +438,7 @@ namespace Umbraco.Core.Models
|
|||||||
|
|
||||||
public override void ChangeTrashedState(bool isTrashed, int parentId = -20)
|
public override void ChangeTrashedState(bool isTrashed, int parentId = -20)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException("Members can't be trashed as no Recycle Bin exists, so use of this method is invalid");
|
throw new NotSupportedException("Members can't be trashed as no Recycle Bin exists, so use of this method is invalid");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Internal experiment - only used for mapping queries.
|
/* Internal experiment - only used for mapping queries.
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
namespace Umbraco.Core.Models.Membership
|
namespace Umbraco.Core.Models.Membership
|
||||||
{
|
{
|
||||||
|
//TODO: THere's still a bunch of properties that don't exist in this use that need to be mapped somehow.
|
||||||
|
|
||||||
internal class UmbracoMembershipMember : MembershipUser
|
internal class UmbracoMembershipMember : MembershipUser
|
||||||
{
|
{
|
||||||
private readonly IMember _member;
|
private readonly IMember _member;
|
||||||
@@ -21,5 +23,44 @@ namespace Umbraco.Core.Models.Membership
|
|||||||
get { return _member.Email; }
|
get { return _member.Email; }
|
||||||
set { _member.Email = value; }
|
set { _member.Email = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override object ProviderUserKey
|
||||||
|
{
|
||||||
|
get { return _member.Key; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public override System.DateTime CreationDate
|
||||||
|
{
|
||||||
|
get { return _member.CreateDate; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string UserName
|
||||||
|
{
|
||||||
|
get { return _member.Username; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Comment
|
||||||
|
{
|
||||||
|
get { return _member.Comments; }
|
||||||
|
set { _member.Comments = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool IsApproved
|
||||||
|
{
|
||||||
|
get { return _member.IsApproved; }
|
||||||
|
set { _member.IsApproved = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool IsLockedOut
|
||||||
|
{
|
||||||
|
get { return _member.IsLockedOut; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public override System.DateTime LastLoginDate
|
||||||
|
{
|
||||||
|
get { return _member.LastLoginDate; }
|
||||||
|
set { _member.LastLoginDate = value; }
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,63 +1,63 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Runtime.Serialization;
|
using System.Runtime.Serialization;
|
||||||
|
|
||||||
namespace Umbraco.Web.Models
|
namespace Umbraco.Core.Models
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a paged result for a model collection
|
/// Represents a paged result for a model collection
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="T"></typeparam>
|
/// <typeparam name="T"></typeparam>
|
||||||
[DataContract(Name = "pagedCollection", Namespace = "")]
|
[DataContract(Name = "pagedCollection", Namespace = "")]
|
||||||
public class PagedResult<T>
|
public class PagedResult<T>
|
||||||
{
|
{
|
||||||
public PagedResult(long totalItems, long pageNumber, long pageSize)
|
public PagedResult(long totalItems, long pageNumber, long pageSize)
|
||||||
{
|
{
|
||||||
TotalItems = totalItems;
|
TotalItems = totalItems;
|
||||||
PageNumber = pageNumber;
|
PageNumber = pageNumber;
|
||||||
PageSize = pageSize;
|
PageSize = pageSize;
|
||||||
|
|
||||||
if (pageSize > 0)
|
if (pageSize > 0)
|
||||||
{
|
{
|
||||||
TotalPages = (long) Math.Ceiling(totalItems/(Decimal) pageSize);
|
TotalPages = (long) Math.Ceiling(totalItems/(Decimal) pageSize);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
TotalPages = 1;
|
TotalPages = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[DataMember(Name = "pageNumber")]
|
[DataMember(Name = "pageNumber")]
|
||||||
public long PageNumber { get; private set; }
|
public long PageNumber { get; private set; }
|
||||||
|
|
||||||
[DataMember(Name = "pageSize")]
|
[DataMember(Name = "pageSize")]
|
||||||
public long PageSize { get; private set; }
|
public long PageSize { get; private set; }
|
||||||
|
|
||||||
[DataMember(Name = "totalPages")]
|
[DataMember(Name = "totalPages")]
|
||||||
public long TotalPages { get; private set; }
|
public long TotalPages { get; private set; }
|
||||||
|
|
||||||
[DataMember(Name = "totalItems")]
|
[DataMember(Name = "totalItems")]
|
||||||
public long TotalItems { get; private set; }
|
public long TotalItems { get; private set; }
|
||||||
|
|
||||||
[DataMember(Name = "items")]
|
[DataMember(Name = "items")]
|
||||||
public IEnumerable<T> Items { get; set; }
|
public IEnumerable<T> Items { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Calculates the skip size based on the paged parameters specified
|
/// Calculates the skip size based on the paged parameters specified
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// Returns 0 if the page number or page size is zero
|
/// Returns 0 if the page number or page size is zero
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
internal int SkipSize
|
internal int SkipSize
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
if (PageNumber > 0 && PageSize > 0)
|
if (PageNumber > 0 && PageSize > 0)
|
||||||
{
|
{
|
||||||
return Convert.ToInt32((PageNumber - 1)*PageSize);
|
return Convert.ToInt32((PageNumber - 1)*PageSize);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2,6 +2,7 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Data;
|
using System.Data;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
using Umbraco.Core.Logging;
|
using Umbraco.Core.Logging;
|
||||||
using Umbraco.Core.Models.Rdbms;
|
using Umbraco.Core.Models.Rdbms;
|
||||||
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
|
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
|
||||||
@@ -17,6 +18,19 @@ namespace Umbraco.Core.Persistence
|
|||||||
|
|
||||||
internal static event CreateTableEventHandler NewTable;
|
internal static event CreateTableEventHandler NewTable;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This will escape single @ symbols for peta poco values so it doesn't think it's a parameter
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="db"></param>
|
||||||
|
/// <param name="value"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static string EscapeAtSymbols(this Database db, string value)
|
||||||
|
{
|
||||||
|
//this fancy regex will only match a single @ not a double, etc...
|
||||||
|
var regex = new Regex("(?<!@)@(?!@)");
|
||||||
|
return regex.Replace(value, "@@");
|
||||||
|
}
|
||||||
|
|
||||||
public static void CreateTable<T>(this Database db)
|
public static void CreateTable<T>(this Database db)
|
||||||
where T : new()
|
where T : new()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -11,5 +11,6 @@ namespace Umbraco.Core.Persistence.Repositories
|
|||||||
/// <param name="groupName"></param>
|
/// <param name="groupName"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
IEnumerable<IMember> GetByMemberGroup(string groupName);
|
IEnumerable<IMember> GetByMemberGroup(string groupName);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -265,8 +265,10 @@ namespace Umbraco.Core.Persistence.Repositories
|
|||||||
//Updates Modified date
|
//Updates Modified date
|
||||||
((Member)entity).UpdatingEntity();
|
((Member)entity).UpdatingEntity();
|
||||||
|
|
||||||
|
var dirtyEntity = (ICanBeDirty) entity;
|
||||||
|
|
||||||
//Look up parent to get and set the correct Path and update SortOrder if ParentId has changed
|
//Look up parent to get and set the correct Path and update SortOrder if ParentId has changed
|
||||||
if (((ICanBeDirty)entity).IsPropertyDirty("ParentId"))
|
if (dirtyEntity.IsPropertyDirty("ParentId"))
|
||||||
{
|
{
|
||||||
var parent = Database.First<NodeDto>("WHERE id = @ParentId", new { ParentId = ((IUmbracoEntity)entity).ParentId });
|
var parent = Database.First<NodeDto>("WHERE id = @ParentId", new { ParentId = ((IUmbracoEntity)entity).ParentId });
|
||||||
((IUmbracoEntity)entity).Path = string.Concat(parent.Path, ",", entity.Id);
|
((IUmbracoEntity)entity).Path = string.Concat(parent.Path, ",", entity.Id);
|
||||||
@@ -302,17 +304,44 @@ namespace Umbraco.Core.Persistence.Repositories
|
|||||||
//Updates the current version - cmsContentVersion
|
//Updates the current version - cmsContentVersion
|
||||||
//Assumes a Version guid exists and Version date (modified date) has been set/updated
|
//Assumes a Version guid exists and Version date (modified date) has been set/updated
|
||||||
Database.Update(dto.ContentVersionDto);
|
Database.Update(dto.ContentVersionDto);
|
||||||
//Updates the cmsMember entry
|
|
||||||
Database.Update(dto);
|
//Updates the cmsMember entry if it has changed
|
||||||
|
var changedCols = new List<string>();
|
||||||
|
if (dirtyEntity.IsPropertyDirty("Email"))
|
||||||
|
{
|
||||||
|
changedCols.Add("Email");
|
||||||
|
}
|
||||||
|
if (dirtyEntity.IsPropertyDirty("Username"))
|
||||||
|
{
|
||||||
|
changedCols.Add("LoginName");
|
||||||
|
}
|
||||||
|
// DO NOT update the password if it is null or empty
|
||||||
|
if (dirtyEntity.IsPropertyDirty("Password") && entity.Password.IsNullOrWhiteSpace() == false)
|
||||||
|
{
|
||||||
|
changedCols.Add("Password");
|
||||||
|
}
|
||||||
|
//only update the changed cols
|
||||||
|
if (changedCols.Count > 0)
|
||||||
|
{
|
||||||
|
Database.Update(dto, changedCols);
|
||||||
|
}
|
||||||
|
|
||||||
//TODO ContentType for the Member entity
|
//TODO ContentType for the Member entity
|
||||||
|
|
||||||
//Create the PropertyData for this version - cmsPropertyData
|
//Create the PropertyData for this version - cmsPropertyData
|
||||||
var propertyFactory = new PropertyFactory(entity.ContentType, entity.Version, entity.Id);
|
var propertyFactory = new PropertyFactory(entity.ContentType, entity.Version, entity.Id);
|
||||||
var propertyDataDtos = propertyFactory.BuildDto(((Member)entity).Properties);
|
|
||||||
var keyDictionary = new Dictionary<int, int>();
|
var keyDictionary = new Dictionary<int, int>();
|
||||||
|
|
||||||
//Add Properties
|
//Add Properties
|
||||||
|
// - don't try to save the property if it doesn't exist (or doesn't have an ID) on the content type
|
||||||
|
// - this can occur if the member type doesn't contain the built-in properties that the
|
||||||
|
// - member object contains.
|
||||||
|
var existingProperties = entity.Properties
|
||||||
|
.Where(property => entity.ContentType.PropertyTypes.Any(x => x.Alias == property.Alias && x.HasIdentity))
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
var propertyDataDtos = propertyFactory.BuildDto(existingProperties);
|
||||||
|
|
||||||
foreach (var propertyDataDto in propertyDataDtos)
|
foreach (var propertyDataDto in propertyDataDtos)
|
||||||
{
|
{
|
||||||
if (propertyDataDto.Id > 0)
|
if (propertyDataDto.Id > 0)
|
||||||
@@ -337,7 +366,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
|||||||
|
|
||||||
UpdatePropertyTags(entity, _tagRepository);
|
UpdatePropertyTags(entity, _tagRepository);
|
||||||
|
|
||||||
((ICanBeDirty)entity).ResetDirtyProperties();
|
dirtyEntity.ResetDirtyProperties();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void PersistDeletedItem(IMember entity)
|
protected override void PersistDeletedItem(IMember entity)
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ using System.Security.Permissions;
|
|||||||
[assembly: InternalsVisibleTo("Concorde.Sync")]
|
[assembly: InternalsVisibleTo("Concorde.Sync")]
|
||||||
[assembly: InternalsVisibleTo("Umbraco.Belle")]
|
[assembly: InternalsVisibleTo("Umbraco.Belle")]
|
||||||
[assembly: InternalsVisibleTo("Umbraco.VisualStudio")]
|
[assembly: InternalsVisibleTo("Umbraco.VisualStudio")]
|
||||||
|
[assembly: InternalsVisibleTo("umbraco.providers")]
|
||||||
|
|
||||||
//allow this to be mocked in our unit tests
|
//allow this to be mocked in our unit tests
|
||||||
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]
|
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]
|
||||||
31
src/Umbraco.Core/PropertyEditors/EmailValidator.cs
Normal file
31
src/Umbraco.Core/PropertyEditors/EmailValidator.cs
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using Umbraco.Core.Models;
|
||||||
|
|
||||||
|
namespace Umbraco.Core.PropertyEditors
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A validator that validates an email address
|
||||||
|
/// </summary>
|
||||||
|
[ValueValidator("Email")]
|
||||||
|
internal sealed class EmailValidator : ManifestValueValidator, IPropertyValidator
|
||||||
|
{
|
||||||
|
public override IEnumerable<ValidationResult> Validate(object value, string config, PreValueCollection preValues, PropertyEditor editor)
|
||||||
|
{
|
||||||
|
var asString = value.ToString();
|
||||||
|
|
||||||
|
var emailVal = new EmailAddressAttribute();
|
||||||
|
|
||||||
|
if (emailVal.IsValid(asString) == false)
|
||||||
|
{
|
||||||
|
//TODO: localize these!
|
||||||
|
yield return new ValidationResult("Email is invalid", new[] { "value" });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<ValidationResult> Validate(object value, PreValueCollection preValues, PropertyEditor editor)
|
||||||
|
{
|
||||||
|
return Validate(value, null, preValues, editor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,7 +6,7 @@ namespace Umbraco.Core.Publishing
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// The result of publishing a content item
|
/// The result of publishing a content item
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal class PublishStatus
|
public class PublishStatus
|
||||||
{
|
{
|
||||||
public PublishStatus()
|
public PublishStatus()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ namespace Umbraco.Core.Publishing
|
|||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// Anything less than 10 = Success!
|
/// Anything less than 10 = Success!
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
internal enum PublishStatusType
|
public enum PublishStatusType
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The publishing was successful.
|
/// The publishing was successful.
|
||||||
|
|||||||
@@ -627,28 +627,53 @@ namespace Umbraco.Core.Services
|
|||||||
/// <param name="content">The <see cref="IContent"/> to publish</param>
|
/// <param name="content">The <see cref="IContent"/> to publish</param>
|
||||||
/// <param name="userId">Optional Id of the User issueing the publishing</param>
|
/// <param name="userId">Optional Id of the User issueing the publishing</param>
|
||||||
/// <returns>True if publishing succeeded, otherwise False</returns>
|
/// <returns>True if publishing succeeded, otherwise False</returns>
|
||||||
|
[Obsolete("Use PublishWithStatus instead, that method will provide more detailed information on the outcome")]
|
||||||
public bool Publish(IContent content, int userId = 0)
|
public bool Publish(IContent content, int userId = 0)
|
||||||
{
|
{
|
||||||
var result = SaveAndPublishDo(content, userId);
|
var result = SaveAndPublishDo(content, userId);
|
||||||
return result.Success;
|
return result.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Publishes a single <see cref="IContent"/> object
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="content">The <see cref="IContent"/> to publish</param>
|
||||||
|
/// <param name="userId">Optional Id of the User issueing the publishing</param>
|
||||||
|
/// <returns>True if publishing succeeded, otherwise False</returns>
|
||||||
|
public Attempt<PublishStatus> PublishWithStatus(IContent content, int userId = 0)
|
||||||
|
{
|
||||||
|
return SaveAndPublishDo(content, userId);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Publishes a <see cref="IContent"/> object and all its children
|
/// Publishes a <see cref="IContent"/> object and all its children
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="content">The <see cref="IContent"/> to publish along with its children</param>
|
/// <param name="content">The <see cref="IContent"/> to publish along with its children</param>
|
||||||
/// <param name="userId">Optional Id of the User issueing the publishing</param>
|
/// <param name="userId">Optional Id of the User issueing the publishing</param>
|
||||||
/// <returns>True if publishing succeeded, otherwise False</returns>
|
/// <returns>True if publishing succeeded, otherwise False</returns>
|
||||||
|
[Obsolete("Use PublishWithChildrenWithStatus instead, that method will provide more detailed information on the outcome and also allows the includeUnpublished flag")]
|
||||||
public bool PublishWithChildren(IContent content, int userId = 0)
|
public bool PublishWithChildren(IContent content, int userId = 0)
|
||||||
{
|
{
|
||||||
var result = PublishWithChildrenDo(content, userId, true);
|
var result = PublishWithChildrenDo(content, userId, true);
|
||||||
|
|
||||||
//This used to just return false only when the parent content failed, otherwise would always return true so we'll
|
//This used to just return false only when the parent content failed, otherwise would always return true so we'll
|
||||||
// do the same thing for the moment
|
// do the same thing for the moment
|
||||||
if (!result.Any(x => x.Result.ContentItem.Id == content.Id))
|
if (!result.Any(x => x.Result.ContentItem.Id == content.Id))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return result.Single(x => x.Result.ContentItem.Id == content.Id).Success;
|
return result.Single(x => x.Result.ContentItem.Id == content.Id).Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Publishes a <see cref="IContent"/> object and all its children
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="content">The <see cref="IContent"/> to publish along with its children</param>
|
||||||
|
/// <param name="userId">Optional Id of the User issueing the publishing</param>
|
||||||
|
/// <param name="includeUnpublished">set to true if you want to also publish children that are currently unpublished</param>
|
||||||
|
/// <returns>True if publishing succeeded, otherwise False</returns>
|
||||||
|
public IEnumerable<Attempt<PublishStatus>> PublishWithChildrenWithStatus(IContent content, int userId = 0, bool includeUnpublished = false)
|
||||||
|
{
|
||||||
|
return PublishWithChildrenDo(content, userId, includeUnpublished);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -669,12 +694,25 @@ namespace Umbraco.Core.Services
|
|||||||
/// <param name="userId">Optional Id of the User issueing the publishing</param>
|
/// <param name="userId">Optional Id of the User issueing the publishing</param>
|
||||||
/// <param name="raiseEvents">Optional boolean indicating whether or not to raise save events.</param>
|
/// <param name="raiseEvents">Optional boolean indicating whether or not to raise save events.</param>
|
||||||
/// <returns>True if publishing succeeded, otherwise False</returns>
|
/// <returns>True if publishing succeeded, otherwise False</returns>
|
||||||
|
[Obsolete("Use SaveAndPublishWithStatus instead, that method will provide more detailed information on the outcome")]
|
||||||
public bool SaveAndPublish(IContent content, int userId = 0, bool raiseEvents = true)
|
public bool SaveAndPublish(IContent content, int userId = 0, bool raiseEvents = true)
|
||||||
{
|
{
|
||||||
var result = SaveAndPublishDo(content, userId, raiseEvents);
|
var result = SaveAndPublishDo(content, userId, raiseEvents);
|
||||||
return result.Success;
|
return result.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Saves and Publishes a single <see cref="IContent"/> object
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="content">The <see cref="IContent"/> to save and publish</param>
|
||||||
|
/// <param name="userId">Optional Id of the User issueing the publishing</param>
|
||||||
|
/// <param name="raiseEvents">Optional boolean indicating whether or not to raise save events.</param>
|
||||||
|
/// <returns>True if publishing succeeded, otherwise False</returns>
|
||||||
|
public Attempt<PublishStatus> SaveAndPublishWithStatus(IContent content, int userId = 0, bool raiseEvents = true)
|
||||||
|
{
|
||||||
|
return SaveAndPublishDo(content, userId, raiseEvents);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Saves a single <see cref="IContent"/> object
|
/// Saves a single <see cref="IContent"/> object
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -1329,42 +1367,30 @@ namespace Umbraco.Core.Services
|
|||||||
}
|
}
|
||||||
|
|
||||||
#region Internal Methods
|
#region Internal Methods
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Internal method that Publishes a single <see cref="IContent"/> object for legacy purposes.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="content">The <see cref="IContent"/> to publish</param>
|
|
||||||
/// <param name="userId">Optional Id of the User issueing the publishing</param>
|
|
||||||
/// <returns>True if publishing succeeded, otherwise False</returns>
|
|
||||||
internal Attempt<PublishStatus> PublishInternal(IContent content, int userId = 0)
|
|
||||||
{
|
|
||||||
return SaveAndPublishDo(content, userId);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
///// <summary>
|
||||||
/// Internal method that Publishes a <see cref="IContent"/> object and all its children for legacy purposes.
|
///// Internal method that Publishes a single <see cref="IContent"/> object for legacy purposes.
|
||||||
/// </summary>
|
///// </summary>
|
||||||
/// <param name="content">The <see cref="IContent"/> to publish along with its children</param>
|
///// <param name="content">The <see cref="IContent"/> to publish</param>
|
||||||
/// <param name="userId">Optional Id of the User issueing the publishing</param>
|
///// <param name="userId">Optional Id of the User issueing the publishing</param>
|
||||||
/// <param name="includeUnpublished">If set to true, this will also publish descendants that are completely unpublished, normally this will only publish children that have previously been published</param>
|
///// <returns>True if publishing succeeded, otherwise False</returns>
|
||||||
/// <returns>True if publishing succeeded, otherwise False</returns>
|
//internal Attempt<PublishStatus> PublishInternal(IContent content, int userId = 0)
|
||||||
internal IEnumerable<Attempt<PublishStatus>> PublishWithChildrenInternal(
|
//{
|
||||||
IContent content, int userId = 0, bool includeUnpublished = false)
|
// return SaveAndPublishDo(content, userId);
|
||||||
{
|
//}
|
||||||
return PublishWithChildrenDo(content, userId, includeUnpublished);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
///// <summary>
|
||||||
/// Saves and Publishes a single <see cref="IContent"/> object
|
///// Internal method that Publishes a <see cref="IContent"/> object and all its children for legacy purposes.
|
||||||
/// </summary>
|
///// </summary>
|
||||||
/// <param name="content">The <see cref="IContent"/> to save and publish</param>
|
///// <param name="content">The <see cref="IContent"/> to publish along with its children</param>
|
||||||
/// <param name="userId">Optional Id of the User issueing the publishing</param>
|
///// <param name="userId">Optional Id of the User issueing the publishing</param>
|
||||||
/// <param name="raiseEvents">Optional boolean indicating whether or not to raise save events.</param>
|
///// <param name="includeUnpublished">If set to true, this will also publish descendants that are completely unpublished, normally this will only publish children that have previously been published</param>
|
||||||
/// <returns>True if publishing succeeded, otherwise False</returns>
|
///// <returns>True if publishing succeeded, otherwise False</returns>
|
||||||
internal Attempt<PublishStatus> SaveAndPublishInternal(IContent content, int userId = 0, bool raiseEvents = true)
|
//internal IEnumerable<Attempt<PublishStatus>> PublishWithChildrenInternal(
|
||||||
{
|
// IContent content, int userId = 0, bool includeUnpublished = false)
|
||||||
return SaveAndPublishDo(content, userId, raiseEvents);
|
//{
|
||||||
}
|
// return PublishWithChildrenDo(content, userId, includeUnpublished);
|
||||||
|
//}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a collection of <see cref="IContent"/> descendants by the first Parent.
|
/// Gets a collection of <see cref="IContent"/> descendants by the first Parent.
|
||||||
@@ -1462,7 +1488,7 @@ namespace Umbraco.Core.Services
|
|||||||
/// then the list will only contain one status item, otherwise it will contain status items for it and all of it's descendants that
|
/// then the list will only contain one status item, otherwise it will contain status items for it and all of it's descendants that
|
||||||
/// are to be published.
|
/// are to be published.
|
||||||
/// </returns>
|
/// </returns>
|
||||||
private IEnumerable<Attempt<PublishStatus>> PublishWithChildrenDo(
|
private IEnumerable<Attempt<PublishStatus>> PublishWithChildrenDo(
|
||||||
IContent content, int userId = 0, bool includeUnpublished = false)
|
IContent content, int userId = 0, bool includeUnpublished = false)
|
||||||
{
|
{
|
||||||
if (content == null) throw new ArgumentNullException("content");
|
if (content == null) throw new ArgumentNullException("content");
|
||||||
|
|||||||
@@ -346,36 +346,7 @@ namespace Umbraco.Core.Services
|
|||||||
Audit.Add(AuditTypes.Delete, string.Format("Delete ContentTypes performed by user"), userId, -1);
|
Audit.Add(AuditTypes.Delete, string.Format("Delete ContentTypes performed by user"), userId, -1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets an <see cref="IMemberType"/> object by its Id
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="id">Id of the <see cref="IMemberType"/> to retrieve</param>
|
|
||||||
/// <returns><see cref="IMemberType"/></returns>
|
|
||||||
public IMemberType GetMemberType(int id)
|
|
||||||
{
|
|
||||||
using (var repository = _repositoryFactory.CreateMemberTypeRepository(_uowProvider.GetUnitOfWork()))
|
|
||||||
{
|
|
||||||
return repository.Get(id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets an <see cref="IMemberType"/> object by its Alias
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="alias">Alias of the <see cref="IMemberType"/> to retrieve</param>
|
|
||||||
/// <returns><see cref="IMemberType"/></returns>
|
|
||||||
public IMemberType GetMemberType(string alias)
|
|
||||||
{
|
|
||||||
using (var repository = _repositoryFactory.CreateMemberTypeRepository(_uowProvider.GetUnitOfWork()))
|
|
||||||
{
|
|
||||||
var query = Query<IMemberType>.Builder.Where(x => x.Alias == alias);
|
|
||||||
var contentTypes = repository.GetByQuery(query);
|
|
||||||
|
|
||||||
return contentTypes.FirstOrDefault();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets an <see cref="IMediaType"/> object by its Id
|
/// Gets an <see cref="IMediaType"/> object by its Id
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Umbraco.Core.Models;
|
using Umbraco.Core.Models;
|
||||||
using Umbraco.Core.Models.Membership;
|
using Umbraco.Core.Models.Membership;
|
||||||
|
using Umbraco.Core.Publishing;
|
||||||
|
|
||||||
namespace Umbraco.Core.Services
|
namespace Umbraco.Core.Services
|
||||||
{
|
{
|
||||||
@@ -246,16 +247,35 @@ namespace Umbraco.Core.Services
|
|||||||
/// <param name="content">The <see cref="IContent"/> to publish</param>
|
/// <param name="content">The <see cref="IContent"/> to publish</param>
|
||||||
/// <param name="userId">Optional Id of the User issueing the publishing</param>
|
/// <param name="userId">Optional Id of the User issueing the publishing</param>
|
||||||
/// <returns>True if publishing succeeded, otherwise False</returns>
|
/// <returns>True if publishing succeeded, otherwise False</returns>
|
||||||
|
[Obsolete("Use PublishWithStatus instead, that method will provide more detailed information on the outcome")]
|
||||||
bool Publish(IContent content, int userId = 0);
|
bool Publish(IContent content, int userId = 0);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Publishes a single <see cref="IContent"/> object
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="content">The <see cref="IContent"/> to publish</param>
|
||||||
|
/// <param name="userId">Optional Id of the User issueing the publishing</param>
|
||||||
|
/// <returns>The published status attempt</returns>
|
||||||
|
Attempt<PublishStatus> PublishWithStatus(IContent content, int userId = 0);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Publishes a <see cref="IContent"/> object and all its children
|
/// Publishes a <see cref="IContent"/> object and all its children
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="content">The <see cref="IContent"/> to publish along with its children</param>
|
/// <param name="content">The <see cref="IContent"/> to publish along with its children</param>
|
||||||
/// <param name="userId">Optional Id of the User issueing the publishing</param>
|
/// <param name="userId">Optional Id of the User issueing the publishing</param>
|
||||||
/// <returns>True if publishing succeeded, otherwise False</returns>
|
/// <returns>True if publishing succeeded, otherwise False</returns>
|
||||||
|
[Obsolete("Use PublishWithChildrenWithStatus instead, that method will provide more detailed information on the outcome and also allows the includeUnpublished flag")]
|
||||||
bool PublishWithChildren(IContent content, int userId = 0);
|
bool PublishWithChildren(IContent content, int userId = 0);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Publishes a <see cref="IContent"/> object and all its children
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="content">The <see cref="IContent"/> to publish along with its children</param>
|
||||||
|
/// <param name="userId">Optional Id of the User issueing the publishing</param>
|
||||||
|
/// <param name="includeUnpublished"></param>
|
||||||
|
/// <returns>The list of statuses for all published items</returns>
|
||||||
|
IEnumerable<Attempt<PublishStatus>> PublishWithChildrenWithStatus(IContent content, int userId = 0, bool includeUnpublished = false);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// UnPublishes a single <see cref="IContent"/> object
|
/// UnPublishes a single <see cref="IContent"/> object
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -271,8 +291,18 @@ namespace Umbraco.Core.Services
|
|||||||
/// <param name="userId">Optional Id of the User issueing the publishing</param>
|
/// <param name="userId">Optional Id of the User issueing the publishing</param>
|
||||||
/// <param name="raiseEvents">Optional boolean indicating whether or not to raise save events.</param>
|
/// <param name="raiseEvents">Optional boolean indicating whether or not to raise save events.</param>
|
||||||
/// <returns>True if publishing succeeded, otherwise False</returns>
|
/// <returns>True if publishing succeeded, otherwise False</returns>
|
||||||
|
[Obsolete("Use SaveAndPublishWithStatus instead, that method will provide more detailed information on the outcome")]
|
||||||
bool SaveAndPublish(IContent content, int userId = 0, bool raiseEvents = true);
|
bool SaveAndPublish(IContent content, int userId = 0, bool raiseEvents = true);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Saves and Publishes a single <see cref="IContent"/> object
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="content">The <see cref="IContent"/> to save and publish</param>
|
||||||
|
/// <param name="userId">Optional Id of the User issueing the publishing</param>
|
||||||
|
/// <param name="raiseEvents">Optional boolean indicating whether or not to raise save events.</param>
|
||||||
|
/// <returns>True if publishing succeeded, otherwise False</returns>
|
||||||
|
Attempt<PublishStatus> SaveAndPublishWithStatus(IContent content, int userId = 0, bool raiseEvents = true);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Permanently deletes an <see cref="IContent"/> object.
|
/// Permanently deletes an <see cref="IContent"/> object.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -66,21 +66,7 @@ namespace Umbraco.Core.Services
|
|||||||
/// <remarks>Deleting a <see cref="IContentType"/> will delete all the <see cref="IContent"/> objects based on this <see cref="IContentType"/></remarks>
|
/// <remarks>Deleting a <see cref="IContentType"/> will delete all the <see cref="IContent"/> objects based on this <see cref="IContentType"/></remarks>
|
||||||
/// <param name="userId">Optional Id of the User deleting the ContentTypes</param>
|
/// <param name="userId">Optional Id of the User deleting the ContentTypes</param>
|
||||||
void Delete(IEnumerable<IContentType> contentTypes, int userId = 0);
|
void Delete(IEnumerable<IContentType> contentTypes, int userId = 0);
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets an <see cref="IMemberType"/> object by its Id
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="id">Id of the <see cref="IMediaType"/> to retrieve</param>
|
|
||||||
/// <returns><see cref="IMediaType"/></returns>
|
|
||||||
IMemberType GetMemberType(int id);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets an <see cref="IMemberType"/> object by its Alias
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="alias">Alias of the <see cref="IMediaType"/> to retrieve</param>
|
|
||||||
/// <returns><see cref="IMediaType"/></returns>
|
|
||||||
IMemberType GetMemberType(string alias);
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets an <see cref="IMediaType"/> object by its Id
|
/// Gets an <see cref="IMediaType"/> object by its Id
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ namespace Umbraco.Core.Services
|
|||||||
IEnumerable<IMember> GetMembersByMemberType(string memberTypeAlias);
|
IEnumerable<IMember> GetMembersByMemberType(string memberTypeAlias);
|
||||||
IEnumerable<IMember> GetMembersByGroup(string memberGroupName);
|
IEnumerable<IMember> GetMembersByGroup(string memberGroupName);
|
||||||
IEnumerable<IMember> GetAllMembers(params int[] ids);
|
IEnumerable<IMember> GetAllMembers(params int[] ids);
|
||||||
|
|
||||||
//TODO: Need to get all members that start with a certain letter
|
//TODO: Need to get all members that start with a certain letter
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -37,5 +37,7 @@ namespace Umbraco.Core.Services
|
|||||||
void Delete(IMember membershipUser);
|
void Delete(IMember membershipUser);
|
||||||
|
|
||||||
void Save(IMember membershipUser);
|
void Save(IMember membershipUser);
|
||||||
|
|
||||||
|
IEnumerable<IMember> FindMembersByEmail(string emailStringToMatch);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -12,7 +12,18 @@ namespace Umbraco.Core.Services
|
|||||||
/// <returns>An Enumerable list of <see cref="IContentType"/> objects</returns>
|
/// <returns>An Enumerable list of <see cref="IContentType"/> objects</returns>
|
||||||
IEnumerable<IMemberType> GetAllMemberTypes(params int[] ids);
|
IEnumerable<IMemberType> GetAllMemberTypes(params int[] ids);
|
||||||
|
|
||||||
IMemberType GetMemberType(string alias);
|
/// <summary>
|
||||||
|
/// Gets an <see cref="IMemberType"/> object by its Id
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="id">Id of the <see cref="IMediaType"/> to retrieve</param>
|
||||||
|
/// <returns><see cref="IMediaType"/></returns>
|
||||||
IMemberType GetMemberType(int id);
|
IMemberType GetMemberType(int id);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets an <see cref="IMemberType"/> object by its Alias
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="alias">Alias of the <see cref="IMediaType"/> to retrieve</param>
|
||||||
|
/// <returns><see cref="IMediaType"/></returns>
|
||||||
|
IMemberType GetMemberType(string alias);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -108,6 +108,25 @@ namespace Umbraco.Core.Services
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Does a search for members that contain the specified string in their email address
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="emailStringToMatch"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public IEnumerable<IMember> FindMembersByEmail(string emailStringToMatch)
|
||||||
|
{
|
||||||
|
var uow = _uowProvider.GetUnitOfWork();
|
||||||
|
using (var repository = _repositoryFactory.CreateMemberRepository(uow))
|
||||||
|
{
|
||||||
|
var query = new Query<IMember>();
|
||||||
|
|
||||||
|
|
||||||
|
query.Where(member => member.Email.Contains(emailStringToMatch));
|
||||||
|
|
||||||
|
return repository.GetByQuery(query);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a list of Members with a certain string property value
|
/// Gets a list of Members with a certain string property value
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -37,17 +37,11 @@ namespace Umbraco.Core.Services
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public IMemberType GetMemberType(string alias)
|
/// <summary>
|
||||||
{
|
/// Gets an <see cref="IMemberType"/> object by its Id
|
||||||
using (var repository = _repositoryFactory.CreateMemberTypeRepository(_uowProvider.GetUnitOfWork()))
|
/// </summary>
|
||||||
{
|
/// <param name="id">Id of the <see cref="IMemberType"/> to retrieve</param>
|
||||||
var query = Query<IMemberType>.Builder.Where(x => x.Alias == alias);
|
/// <returns><see cref="IMemberType"/></returns>
|
||||||
var memberTypes = repository.GetByQuery(query);
|
|
||||||
|
|
||||||
return memberTypes.FirstOrDefault();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public IMemberType GetMemberType(int id)
|
public IMemberType GetMemberType(int id)
|
||||||
{
|
{
|
||||||
using (var repository = _repositoryFactory.CreateMemberTypeRepository(_uowProvider.GetUnitOfWork()))
|
using (var repository = _repositoryFactory.CreateMemberTypeRepository(_uowProvider.GetUnitOfWork()))
|
||||||
@@ -56,5 +50,21 @@ namespace Umbraco.Core.Services
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets an <see cref="IMemberType"/> object by its Alias
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="alias">Alias of the <see cref="IMemberType"/> to retrieve</param>
|
||||||
|
/// <returns><see cref="IMemberType"/></returns>
|
||||||
|
public IMemberType GetMemberType(string alias)
|
||||||
|
{
|
||||||
|
using (var repository = _repositoryFactory.CreateMemberTypeRepository(_uowProvider.GetUnitOfWork()))
|
||||||
|
{
|
||||||
|
var query = Query<IMemberType>.Builder.Where(x => x.Alias == alias);
|
||||||
|
var contentTypes = repository.GetByQuery(query);
|
||||||
|
|
||||||
|
return contentTypes.FirstOrDefault();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -358,6 +358,7 @@
|
|||||||
<Compile Include="Models\Membership\MembershipExtensions.cs" />
|
<Compile Include="Models\Membership\MembershipExtensions.cs" />
|
||||||
<Compile Include="Models\Membership\UmbracoMembershipMember.cs" />
|
<Compile Include="Models\Membership\UmbracoMembershipMember.cs" />
|
||||||
<Compile Include="Models\Membership\UmbracoMembershipUser.cs" />
|
<Compile Include="Models\Membership\UmbracoMembershipUser.cs" />
|
||||||
|
<Compile Include="Models\PagedResult.cs" />
|
||||||
<Compile Include="Models\PreValue.cs" />
|
<Compile Include="Models\PreValue.cs" />
|
||||||
<Compile Include="Models\MemberType.cs" />
|
<Compile Include="Models\MemberType.cs" />
|
||||||
<Compile Include="Models\PreValueCollection.cs" />
|
<Compile Include="Models\PreValueCollection.cs" />
|
||||||
@@ -450,6 +451,7 @@
|
|||||||
<Compile Include="Persistence\Repositories\TagsRepository.cs" />
|
<Compile Include="Persistence\Repositories\TagsRepository.cs" />
|
||||||
<Compile Include="PropertyEditors\BackwardsCompatibleData.cs" />
|
<Compile Include="PropertyEditors\BackwardsCompatibleData.cs" />
|
||||||
<Compile Include="PropertyEditors\BackwardsCompatibleDataType.cs" />
|
<Compile Include="PropertyEditors\BackwardsCompatibleDataType.cs" />
|
||||||
|
<Compile Include="PropertyEditors\EmailValidator.cs" />
|
||||||
<Compile Include="PropertyEditors\IParameterEditor.cs" />
|
<Compile Include="PropertyEditors\IParameterEditor.cs" />
|
||||||
<Compile Include="PropertyEditors\LegacyParameterEditorAliasConverter.cs" />
|
<Compile Include="PropertyEditors\LegacyParameterEditorAliasConverter.cs" />
|
||||||
<Compile Include="PropertyEditors\LegacyPropertyEditorIdToAliasConverter.cs" />
|
<Compile Include="PropertyEditors\LegacyPropertyEditorIdToAliasConverter.cs" />
|
||||||
|
|||||||
@@ -189,6 +189,63 @@ namespace Umbraco.Tests.Persistence.Repositories
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void MemberRepository_Does_Not_Replace_Password_When_Null()
|
||||||
|
{
|
||||||
|
IMember sut;
|
||||||
|
var provider = new PetaPocoUnitOfWorkProvider();
|
||||||
|
var unitOfWork = provider.GetUnitOfWork();
|
||||||
|
MemberTypeRepository memberTypeRepository;
|
||||||
|
using (var repository = CreateRepository(unitOfWork, out memberTypeRepository))
|
||||||
|
{
|
||||||
|
var memberType = MockedContentTypes.CreateSimpleMemberType();
|
||||||
|
memberTypeRepository.AddOrUpdate(memberType);
|
||||||
|
unitOfWork.Commit();
|
||||||
|
|
||||||
|
var member = MockedMember.CreateSimpleContent(memberType, "Johnny Hefty", "johnny@example.com", "123", "hefty", -1);
|
||||||
|
repository.AddOrUpdate(member);
|
||||||
|
unitOfWork.Commit();
|
||||||
|
|
||||||
|
sut = repository.Get(member.Id);
|
||||||
|
//when the password is null it will not overwrite what is already there.
|
||||||
|
sut.Password = null;
|
||||||
|
repository.AddOrUpdate(sut);
|
||||||
|
unitOfWork.Commit();
|
||||||
|
sut = repository.Get(member.Id);
|
||||||
|
|
||||||
|
Assert.That(sut.Password, Is.EqualTo("123"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void MemberRepository_Can_Update_Email_And_Login_When_Changed()
|
||||||
|
{
|
||||||
|
IMember sut;
|
||||||
|
var provider = new PetaPocoUnitOfWorkProvider();
|
||||||
|
var unitOfWork = provider.GetUnitOfWork();
|
||||||
|
MemberTypeRepository memberTypeRepository;
|
||||||
|
using (var repository = CreateRepository(unitOfWork, out memberTypeRepository))
|
||||||
|
{
|
||||||
|
var memberType = MockedContentTypes.CreateSimpleMemberType();
|
||||||
|
memberTypeRepository.AddOrUpdate(memberType);
|
||||||
|
unitOfWork.Commit();
|
||||||
|
|
||||||
|
var member = MockedMember.CreateSimpleContent(memberType, "Johnny Hefty", "johnny@example.com", "123", "hefty", -1);
|
||||||
|
repository.AddOrUpdate(member);
|
||||||
|
unitOfWork.Commit();
|
||||||
|
|
||||||
|
sut = repository.Get(member.Id);
|
||||||
|
sut.Username = "This is new";
|
||||||
|
sut.Email = "thisisnew@hello.com";
|
||||||
|
repository.AddOrUpdate(sut);
|
||||||
|
unitOfWork.Commit();
|
||||||
|
sut = repository.Get(member.Id);
|
||||||
|
|
||||||
|
Assert.That(sut.Email, Is.EqualTo("thisisnew@hello.com"));
|
||||||
|
Assert.That(sut.Username, Is.EqualTo("This is new"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void Can_Create_Correct_Subquery()
|
public void Can_Create_Correct_Subquery()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ function sectionsDirective($timeout, $window, navigationService, sectionResource
|
|||||||
|
|
||||||
scope.maxSections = 7;
|
scope.maxSections = 7;
|
||||||
scope.overflowingSections = 0;
|
scope.overflowingSections = 0;
|
||||||
|
scope.sections = [];
|
||||||
|
|
||||||
function loadSections(){
|
function loadSections(){
|
||||||
sectionResource.getSections()
|
sectionResource.getSections()
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
angular.module('umbraco.directives.validation')
|
angular.module('umbraco.directives.validation')
|
||||||
.directive('valCompare',function () {
|
.directive('valCompare',function () {
|
||||||
return {
|
return {
|
||||||
require: "ngModel",
|
require: "ngModel",
|
||||||
link: function(scope, elem, attrs, ctrl) {
|
link: function (scope, elem, attrs, ctrl) {
|
||||||
|
|
||||||
|
//TODO: Pretty sure this should be done using a requires ^form in the directive declaration
|
||||||
var otherInput = elem.inheritedData("$formController")[attrs.valCompare];
|
var otherInput = elem.inheritedData("$formController")[attrs.valCompare];
|
||||||
|
|
||||||
ctrl.$parsers.push(function(value) {
|
ctrl.$parsers.push(function(value) {
|
||||||
|
|||||||
@@ -102,7 +102,9 @@ function valPropertyMsg(serverValidationManager) {
|
|||||||
|
|
||||||
var errCount = 0;
|
var errCount = 0;
|
||||||
for (var e in formCtrl.$error) {
|
for (var e in formCtrl.$error) {
|
||||||
errCount++;
|
if (e) {
|
||||||
|
errCount++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((errCount === 1 && formCtrl.$error.valPropertyMsg !== undefined) ||
|
if ((errCount === 1 && formCtrl.$error.valPropertyMsg !== undefined) ||
|
||||||
|
|||||||
@@ -6,17 +6,36 @@
|
|||||||
* NOTE: there's already an ng-pattern but this requires that a regex expression is set, not a regex string
|
* NOTE: there's already an ng-pattern but this requires that a regex expression is set, not a regex string
|
||||||
**/
|
**/
|
||||||
function valRegex() {
|
function valRegex() {
|
||||||
|
|
||||||
return {
|
return {
|
||||||
require: 'ngModel',
|
require: 'ngModel',
|
||||||
restrict: "A",
|
restrict: "A",
|
||||||
link: function (scope, elm, attrs, ctrl) {
|
link: function (scope, elm, attrs, ctrl) {
|
||||||
|
|
||||||
|
var flags = "";
|
||||||
|
if (attrs.valRegexFlags) {
|
||||||
|
try {
|
||||||
|
flags = scope.$eval(attrs.valRegexFlags);
|
||||||
|
if (!flags) {
|
||||||
|
flags = attrs.valRegexFlags;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
flags = attrs.valRegexFlags;
|
||||||
|
}
|
||||||
|
}
|
||||||
var regex;
|
var regex;
|
||||||
try {
|
try {
|
||||||
regex = new RegExp(scope.$eval(attrs.valRegex));
|
var resolved = scope.$eval(attrs.valRegex);
|
||||||
|
if (resolved) {
|
||||||
|
regex = new RegExp(resolved, flags);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
regex = new RegExp(attrs.valRegex, flags);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch(e) {
|
catch(e) {
|
||||||
regex = new RegExp(attrs.valRegex);
|
regex = new RegExp(attrs.valRegex, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
var patternValidator = function (viewValue) {
|
var patternValidator = function (viewValue) {
|
||||||
|
|||||||
@@ -213,7 +213,7 @@ function contentEditingHelper($location, $routeParams, notificationsService, ser
|
|||||||
}
|
}
|
||||||
|
|
||||||
args.scope.$broadcast("saved", { scope: args.scope });
|
args.scope.$broadcast("saved", { scope: args.scope });
|
||||||
if (!this.redirectToCreatedContent(args.newContent.id)) {
|
if (!this.redirectToCreatedContent(args.redirectId ? args.redirectId : args.newContent.id)) {
|
||||||
|
|
||||||
//we are not redirecting because this is not new content, it is existing content. In this case
|
//we are not redirecting because this is not new content, it is existing content. In this case
|
||||||
// we need to detect what properties have changed and re-bind them with the server data.
|
// we need to detect what properties have changed and re-bind them with the server data.
|
||||||
|
|||||||
@@ -203,7 +203,7 @@ function umbDataFormatter() {
|
|||||||
|
|
||||||
/** formats the display model used to display the member to the model used to save the member */
|
/** formats the display model used to display the member to the model used to save the member */
|
||||||
formatMemberPostData: function(displayModel, action) {
|
formatMemberPostData: function(displayModel, action) {
|
||||||
//this is basically the same as for media but we need to explicitly add the username,email to the save model
|
//this is basically the same as for media but we need to explicitly add the username,email, password to the save model
|
||||||
var saveModel = this.formatMediaPostData(displayModel, action);
|
var saveModel = this.formatMediaPostData(displayModel, action);
|
||||||
|
|
||||||
var genericTab = _.find(displayModel.tabs, function (item) {
|
var genericTab = _.find(displayModel.tabs, function (item) {
|
||||||
@@ -216,8 +216,17 @@ function umbDataFormatter() {
|
|||||||
var propEmail = _.find(genericTab.properties, function (item) {
|
var propEmail = _.find(genericTab.properties, function (item) {
|
||||||
return item.alias === "_umb_email";
|
return item.alias === "_umb_email";
|
||||||
});
|
});
|
||||||
|
var propPass = _.find(genericTab.properties, function (item) {
|
||||||
|
return item.alias === "_umb_password";
|
||||||
|
});
|
||||||
saveModel.email = propEmail.value;
|
saveModel.email = propEmail.value;
|
||||||
saveModel.username = propLogin.value;
|
saveModel.username = propLogin.value;
|
||||||
|
//NOTE: This would only be set for new members!
|
||||||
|
if (angular.isString(propPass.value)) {
|
||||||
|
// if we are resetting or changing passwords then that data will come from the property editor and
|
||||||
|
// it's value will be an object not just a string.
|
||||||
|
saveModel.password = propPass.value;
|
||||||
|
}
|
||||||
|
|
||||||
return saveModel;
|
return saveModel;
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
<form novalidate name="contentForm"
|
<form novalidate name="contentForm"
|
||||||
ng-controller="Umbraco.Editors.DataType.EditController"
|
ng-controller="Umbraco.Editors.DataType.EditController"
|
||||||
ng-show="loaded"
|
ng-show="loaded"
|
||||||
ng-submit="save()">
|
ng-submit="save()"
|
||||||
|
val-status-changed>
|
||||||
<umb-panel val-show-validation>
|
<umb-panel val-show-validation>
|
||||||
|
|
||||||
<umb-header>
|
<umb-header>
|
||||||
|
|||||||
@@ -65,6 +65,8 @@ function MemberEditController($scope, $routeParams, $q, $timeout, $window, membe
|
|||||||
contentEditingHelper.handleSuccessfulSave({
|
contentEditingHelper.handleSuccessfulSave({
|
||||||
scope: $scope,
|
scope: $scope,
|
||||||
newContent: data,
|
newContent: data,
|
||||||
|
//specify a custom id to redirect to since we want to use the GUID
|
||||||
|
redirectId: data.key,
|
||||||
rebindCallback: contentEditingHelper.reBindChangedProperties($scope.content, data)
|
rebindCallback: contentEditingHelper.reBindChangedProperties($scope.content, data)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,40 @@
|
|||||||
|
angular.module("umbraco").controller("Umbraco.PropertyEditors.ChangePasswordController",
|
||||||
|
function($scope) {
|
||||||
|
|
||||||
|
//the model config will contain an object, if it does not we'll create defaults
|
||||||
|
//NOTE: We will not support doing the password regex on the client side because the regex on the server side
|
||||||
|
//based on the membership provider cannot always be ported to js from .net directly.
|
||||||
|
/*
|
||||||
|
{
|
||||||
|
requiresQuestionAnswer: true/false,
|
||||||
|
enableReset: true/false,
|
||||||
|
minPasswordLength: 10
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
//set defaults if they are not available
|
||||||
|
if (!$scope.model.config || !$scope.model.config.requiresQuestionAnswer) {
|
||||||
|
$scope.model.config.requiresQuestionAnswer = false;
|
||||||
|
}
|
||||||
|
if (!$scope.model.config || !$scope.model.config.enableReset) {
|
||||||
|
$scope.model.config.enableReset = true;
|
||||||
|
}
|
||||||
|
if (!$scope.model.config || !$scope.model.config.minPasswordLength) {
|
||||||
|
$scope.model.config.minPasswordLength = 7;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
$scope.confirm = "";
|
||||||
|
|
||||||
|
$scope.hasPassword = $scope.model.value !== undefined && $scope.model.value !== null && $scope.model.value !== "";
|
||||||
|
|
||||||
|
$scope.changing = !$scope.hasPassword;
|
||||||
|
|
||||||
|
$scope.doChange = function() {
|
||||||
|
$scope.changing = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.cancelChange = function() {
|
||||||
|
$scope.changing = false;
|
||||||
|
};
|
||||||
|
});
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
<div ng-controller="Umbraco.PropertyEditors.ChangePasswordController" ng-switch="changing">
|
||||||
|
<div ng-switch-when="false">
|
||||||
|
<!--<a href="" ng-click="doChange()">Change password</a> -->
|
||||||
|
<div class="control-group warning">
|
||||||
|
<span class="help-block">Password changing or resetting is currently not supported</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div ng-switch-when="true">
|
||||||
|
<div class="control-group">
|
||||||
|
|
||||||
|
<input type="text" name="password" ng-model="model.value" id="{{model.alias}}"
|
||||||
|
class="umb-editor umb-textstring textstring"
|
||||||
|
required
|
||||||
|
val-server
|
||||||
|
ng-minlength="{{model.config.minPasswordLength}}" />
|
||||||
|
|
||||||
|
<span class="help-inline" val-msg-for="password" val-toggle-msg="required">Required</span>
|
||||||
|
<span class="help-inline" val-msg-for="password" val-toggle-msg="minlength">Minimum {{model.config.minPasswordLength}} characters</span>
|
||||||
|
<span class="help-inline" val-msg-for="password" val-toggle-msg="valServer"></span>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="control-group">
|
||||||
|
|
||||||
|
<input type="text" name="confirmpassword" ng-model="model.confirm" id="{{model.alias}}"
|
||||||
|
class="umb-editor umb-textstring textstring"
|
||||||
|
val-compare="password" />
|
||||||
|
|
||||||
|
<span class="help-inline" val-msg-for="confirmpassword" val-toggle-msg="valCompare">Passwords must match</span>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<!--<a href="" ng-click="cancelChange()" ng-show="hasPassword">Cancel</a> -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
angular.module("umbraco")
|
|
||||||
.controller("Umbraco.PropertyEditors.EmailController",
|
|
||||||
function($rootScope, $scope, dialogService, $routeParams, contentResource, contentTypeResource, editorContextService, notificationsService) {
|
|
||||||
|
|
||||||
|
|
||||||
});
|
|
||||||
@@ -1,3 +1,13 @@
|
|||||||
<input type="email" name="textbox" ng-model="model.value" id="{{model.alias}}" class="umb-editor umb-textstring textstring" val-server="value" />
|
<div>
|
||||||
<span class="help-inline" val-msg-for="textbox" val-toggle-msg="email">Invalid email</span>
|
|
||||||
<span class="help-inline" val-msg-for="textbox" val-toggle-msg="valServer"></span>
|
<input type="email" name="textbox"
|
||||||
|
ng-model="model.value"
|
||||||
|
id="{{model.alias}}"
|
||||||
|
class="umb-editor umb-textstring textstring"
|
||||||
|
ng-required="model.config.IsRequired"
|
||||||
|
val-server="value" />
|
||||||
|
|
||||||
|
<span class="help-inline" val-msg-for="textbox" val-toggle-msg="required">Required</span>
|
||||||
|
<span class="help-inline" val-msg-for="textbox" val-toggle-msg="email">Invalid email</span>
|
||||||
|
<span class="help-inline" val-msg-for="textbox" val-toggle-msg="valServer"></span>
|
||||||
|
</div>
|
||||||
|
|||||||
@@ -1,2 +1,9 @@
|
|||||||
<input type="text" name="textbox" ng-model="model.value" id="{{model.alias}}" class="umb-editor umb-textstring textstring" val-server="value" />
|
<div>
|
||||||
<span class="help-inline" val-msg-for="textbox" val-toggle-msg="valServer"></span>
|
<input type="text" name="textbox" ng-model="model.value" id="{{model.alias}}"
|
||||||
|
class="umb-editor umb-textstring textstring"
|
||||||
|
val-server="value"
|
||||||
|
ng-required="model.config.IsRequired" />
|
||||||
|
|
||||||
|
<span class="help-inline" val-msg-for="textbox" val-toggle-msg="required">Required</span>
|
||||||
|
<span class="help-inline" val-msg-for="textbox" val-toggle-msg="valServer"></span>
|
||||||
|
</div>
|
||||||
|
|||||||
@@ -185,32 +185,7 @@ namespace Umbraco.Web.Editors
|
|||||||
// * any file attachments have been saved to their temporary location for us to use
|
// * any file attachments have been saved to their temporary location for us to use
|
||||||
// * we have a reference to the DTO object and the persisted object
|
// * we have a reference to the DTO object and the persisted object
|
||||||
// * Permissions are valid
|
// * Permissions are valid
|
||||||
|
|
||||||
UpdateName(contentItem);
|
|
||||||
|
|
||||||
//TODO: We need to support 'send to publish'
|
|
||||||
|
|
||||||
contentItem.PersistedContent.ExpireDate = contentItem.ExpireDate;
|
|
||||||
contentItem.PersistedContent.ReleaseDate = contentItem.ReleaseDate;
|
|
||||||
//only set the template if it didn't change
|
|
||||||
var templateChanged = (contentItem.PersistedContent.Template == null && contentItem.TemplateAlias.IsNullOrWhiteSpace() == false)
|
|
||||||
|| (contentItem.PersistedContent.Template != null && contentItem.PersistedContent.Template.Alias != contentItem.TemplateAlias)
|
|
||||||
|| (contentItem.PersistedContent.Template != null && contentItem.TemplateAlias.IsNullOrWhiteSpace());
|
|
||||||
if (templateChanged)
|
|
||||||
{
|
|
||||||
var template = Services.FileService.GetTemplate(contentItem.TemplateAlias);
|
|
||||||
if (template == null && contentItem.TemplateAlias.IsNullOrWhiteSpace() == false)
|
|
||||||
{
|
|
||||||
//ModelState.AddModelError("Template", "No template exists with the specified alias: " + contentItem.TemplateAlias);
|
|
||||||
LogHelper.Warn<ContentController>("No template exists with the specified alias: " + contentItem.TemplateAlias);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//NOTE: this could be null if there was a template and the posted template is null, this should remove the assigned template
|
|
||||||
contentItem.PersistedContent.Template = template;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MapPropertyValues(contentItem);
|
MapPropertyValues(contentItem);
|
||||||
|
|
||||||
//We need to manually check the validation results here because:
|
//We need to manually check the validation results here because:
|
||||||
@@ -255,7 +230,7 @@ namespace Umbraco.Web.Editors
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
//publish the item and check if it worked, if not we will show a diff msg below
|
//publish the item and check if it worked, if not we will show a diff msg below
|
||||||
publishStatus = ((ContentService)Services.ContentService).SaveAndPublishInternal(contentItem.PersistedContent, (int)Security.CurrentUser.Id);
|
publishStatus = Services.ContentService.SaveAndPublishWithStatus(contentItem.PersistedContent, (int)Security.CurrentUser.Id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -281,6 +256,40 @@ namespace Umbraco.Web.Editors
|
|||||||
return display;
|
return display;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Maps the dto property values to the persisted model
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="contentItem"></param>
|
||||||
|
private void MapPropertyValues(ContentItemSave contentItem)
|
||||||
|
{
|
||||||
|
UpdateName(contentItem);
|
||||||
|
|
||||||
|
//TODO: We need to support 'send to publish'
|
||||||
|
|
||||||
|
contentItem.PersistedContent.ExpireDate = contentItem.ExpireDate;
|
||||||
|
contentItem.PersistedContent.ReleaseDate = contentItem.ReleaseDate;
|
||||||
|
//only set the template if it didn't change
|
||||||
|
var templateChanged = (contentItem.PersistedContent.Template == null && contentItem.TemplateAlias.IsNullOrWhiteSpace() == false)
|
||||||
|
|| (contentItem.PersistedContent.Template != null && contentItem.PersistedContent.Template.Alias != contentItem.TemplateAlias)
|
||||||
|
|| (contentItem.PersistedContent.Template != null && contentItem.TemplateAlias.IsNullOrWhiteSpace());
|
||||||
|
if (templateChanged)
|
||||||
|
{
|
||||||
|
var template = Services.FileService.GetTemplate(contentItem.TemplateAlias);
|
||||||
|
if (template == null && contentItem.TemplateAlias.IsNullOrWhiteSpace() == false)
|
||||||
|
{
|
||||||
|
//ModelState.AddModelError("Template", "No template exists with the specified alias: " + contentItem.TemplateAlias);
|
||||||
|
LogHelper.Warn<ContentController>("No template exists with the specified alias: " + contentItem.TemplateAlias);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//NOTE: this could be null if there was a template and the posted template is null, this should remove the assigned template
|
||||||
|
contentItem.PersistedContent.Template = template;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
base.MapPropertyValues(contentItem);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Publishes a document with a given ID
|
/// Publishes a document with a given ID
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -78,7 +78,12 @@ namespace Umbraco.Web.Editors
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void MapPropertyValues<TPersisted>(ContentBaseItemSave<TPersisted> contentItem)
|
/// <summary>
|
||||||
|
/// Maps the dto property values to the persisted model
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TPersisted"></typeparam>
|
||||||
|
/// <param name="contentItem"></param>
|
||||||
|
protected virtual void MapPropertyValues<TPersisted>(ContentBaseItemSave<TPersisted> contentItem)
|
||||||
where TPersisted : IContentBase
|
where TPersisted : IContentBase
|
||||||
{
|
{
|
||||||
//Map the property values
|
//Map the property values
|
||||||
|
|||||||
@@ -287,8 +287,6 @@ namespace Umbraco.Web.Editors
|
|||||||
// * we have a reference to the DTO object and the persisted object
|
// * we have a reference to the DTO object and the persisted object
|
||||||
// * Permissions are valid
|
// * Permissions are valid
|
||||||
|
|
||||||
UpdateName(contentItem);
|
|
||||||
|
|
||||||
MapPropertyValues(contentItem);
|
MapPropertyValues(contentItem);
|
||||||
|
|
||||||
//We need to manually check the validation results here because:
|
//We need to manually check the validation results here because:
|
||||||
@@ -331,6 +329,18 @@ namespace Umbraco.Web.Editors
|
|||||||
return display;
|
return display;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Maps the property values to the persisted entity
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="contentItem"></param>
|
||||||
|
protected override void MapPropertyValues<TPersisted>(ContentBaseItemSave<TPersisted> contentItem)
|
||||||
|
{
|
||||||
|
UpdateName(contentItem);
|
||||||
|
|
||||||
|
//use the base method to map the rest of the properties
|
||||||
|
base.MapPropertyValues(contentItem);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Change the sort order for media
|
/// Change the sort order for media
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -1,16 +1,18 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.ComponentModel.DataAnnotations;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Web.Http;
|
using System.Web.Http;
|
||||||
using System.Web.Http.ModelBinding;
|
using System.Web.Http.ModelBinding;
|
||||||
|
using System.Web.Security;
|
||||||
using AutoMapper;
|
using AutoMapper;
|
||||||
using Examine.LuceneEngine.SearchCriteria;
|
using Examine.LuceneEngine.SearchCriteria;
|
||||||
using Examine.SearchCriteria;
|
using Examine.SearchCriteria;
|
||||||
using Umbraco.Core.Models;
|
using Umbraco.Core.Models;
|
||||||
|
using Umbraco.Core.Models.EntityBase;
|
||||||
using Umbraco.Web.WebApi;
|
using Umbraco.Web.WebApi;
|
||||||
using Umbraco.Web.Models.ContentEditing;
|
using Umbraco.Web.Models.ContentEditing;
|
||||||
using Umbraco.Web.Mvc;
|
using Umbraco.Web.Mvc;
|
||||||
@@ -19,7 +21,6 @@ using Umbraco.Web.WebApi.Filters;
|
|||||||
using umbraco;
|
using umbraco;
|
||||||
using Constants = Umbraco.Core.Constants;
|
using Constants = Umbraco.Core.Constants;
|
||||||
using Examine;
|
using Examine;
|
||||||
using System.Web.Security;
|
|
||||||
using Member = umbraco.cms.businesslogic.member.Member;
|
using Member = umbraco.cms.businesslogic.member.Member;
|
||||||
|
|
||||||
namespace Umbraco.Web.Editors
|
namespace Umbraco.Web.Editors
|
||||||
@@ -77,9 +78,8 @@ namespace Umbraco.Web.Editors
|
|||||||
/// Gets an empty content item for the
|
/// Gets an empty content item for the
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="contentTypeAlias"></param>
|
/// <param name="contentTypeAlias"></param>
|
||||||
/// <param name="parentId"></param>
|
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public MemberDisplay GetEmpty(string contentTypeAlias, string username, string password)
|
public MemberDisplay GetEmpty(string contentTypeAlias)
|
||||||
{
|
{
|
||||||
var contentType = Services.MemberTypeService.GetMemberType(contentTypeAlias);
|
var contentType = Services.MemberTypeService.GetMemberType(contentTypeAlias);
|
||||||
if (contentType == null)
|
if (contentType == null)
|
||||||
@@ -87,7 +87,7 @@ namespace Umbraco.Web.Editors
|
|||||||
throw new HttpResponseException(HttpStatusCode.NotFound);
|
throw new HttpResponseException(HttpStatusCode.NotFound);
|
||||||
}
|
}
|
||||||
|
|
||||||
var emptyContent = new Core.Models.Member("", "", "", "", -1, contentType);
|
var emptyContent = new Core.Models.Member("", contentType);
|
||||||
return Mapper.Map<IMember, MemberDisplay>(emptyContent);
|
return Mapper.Map<IMember, MemberDisplay>(emptyContent);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,10 +96,16 @@ namespace Umbraco.Web.Editors
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
[FileUploadCleanupFilter]
|
[FileUploadCleanupFilter]
|
||||||
|
[MembershipProviderValidationFilter]
|
||||||
public MemberDisplay PostSave(
|
public MemberDisplay PostSave(
|
||||||
[ModelBinder(typeof(MemberBinder))]
|
[ModelBinder(typeof(MemberBinder))]
|
||||||
MemberSave contentItem)
|
MemberSave contentItem)
|
||||||
{
|
{
|
||||||
|
if (Membership.Provider.Name != Constants.Conventions.Member.UmbracoMemberProviderName)
|
||||||
|
{
|
||||||
|
throw new NotSupportedException("Currently the member editor does not support providers that are not the default Umbraco membership provider ");
|
||||||
|
}
|
||||||
|
|
||||||
//If we've reached here it means:
|
//If we've reached here it means:
|
||||||
// * Our model has been bound
|
// * Our model has been bound
|
||||||
// * and validated
|
// * and validated
|
||||||
@@ -107,35 +113,53 @@ namespace Umbraco.Web.Editors
|
|||||||
// * we have a reference to the DTO object and the persisted object
|
// * we have a reference to the DTO object and the persisted object
|
||||||
// * Permissions are valid
|
// * Permissions are valid
|
||||||
|
|
||||||
UpdateName(contentItem);
|
//map the properties to the persisted entity
|
||||||
|
|
||||||
//map the custom properties
|
|
||||||
contentItem.PersistedContent.Email = contentItem.Email;
|
|
||||||
//TODO: If we allow changing the alias then we'll need to change URLs, etc... in the editor, would prefer to use
|
|
||||||
// a unique id but then need to figure out how to handle that with custom membership providers - waiting on feedback from morten.
|
|
||||||
|
|
||||||
MapPropertyValues(contentItem);
|
MapPropertyValues(contentItem);
|
||||||
|
|
||||||
//We need to manually check the validation results here because:
|
//Unlike content/media - if there are errors for a member, we do NOT proceed to save them, we cannot so return the errors
|
||||||
// * We still need to save the entity even if there are validation value errors
|
if (ModelState.IsValid == false)
|
||||||
// * Depending on if the entity is new, and if there are non property validation errors (i.e. the name is null)
|
{
|
||||||
// then we cannot continue saving, we can only display errors
|
var forDisplay = Mapper.Map<IMember, MemberDisplay>(contentItem.PersistedContent);
|
||||||
// * If there are validation errors and they were attempting to publish, we can only save, NOT publish and display
|
forDisplay.Errors = ModelState.ToErrorDictionary();
|
||||||
// a message indicating this
|
throw new HttpResponseException(Request.CreateValidationErrorResponse(forDisplay));
|
||||||
if (!ModelState.IsValid)
|
|
||||||
{
|
|
||||||
if (ValidationHelper.ModelHasRequiredForPersistenceErrors(contentItem)
|
|
||||||
&& (contentItem.Action == ContentSaveAction.SaveNew))
|
|
||||||
{
|
|
||||||
//ok, so the absolute mandatory data is invalid and it's new, we cannot actually continue!
|
|
||||||
// add the modelstate to the outgoing object and throw validation response
|
|
||||||
var forDisplay = Mapper.Map<IMember, MemberDisplay>(contentItem.PersistedContent);
|
|
||||||
forDisplay.Errors = ModelState.ToErrorDictionary();
|
|
||||||
throw new HttpResponseException(Request.CreateValidationErrorResponse(forDisplay));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO: WE need to support this! - requires UI updates, etc...
|
||||||
|
if (Membership.Provider.RequiresQuestionAndAnswer)
|
||||||
|
{
|
||||||
|
throw new NotSupportedException("Currently the member editor does not support providers that have RequiresQuestionAndAnswer specified");
|
||||||
|
}
|
||||||
|
|
||||||
|
//Depending on the action we need to first do a create or update using the membership provider
|
||||||
|
// this ensures that passwords are formatted correclty and also performs the validation on the provider itself.
|
||||||
|
switch (contentItem.Action)
|
||||||
|
{
|
||||||
|
case ContentSaveAction.Save:
|
||||||
|
//TODO: Update with the provider! - change password, etc...
|
||||||
|
break;
|
||||||
|
case ContentSaveAction.SaveNew:
|
||||||
|
MembershipCreateStatus status;
|
||||||
|
CreateWithUmbracoProvider(contentItem, out status);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
//we don't support anything else for members
|
||||||
|
throw new HttpResponseException(HttpStatusCode.NotFound);
|
||||||
|
}
|
||||||
|
|
||||||
|
//If we've had problems creating/updating the user with the provider then return the error
|
||||||
|
if (ModelState.IsValid == false)
|
||||||
|
{
|
||||||
|
var forDisplay = Mapper.Map<IMember, MemberDisplay>(contentItem.PersistedContent);
|
||||||
|
forDisplay.Errors = ModelState.ToErrorDictionary();
|
||||||
|
throw new HttpResponseException(Request.CreateValidationErrorResponse(forDisplay));
|
||||||
|
}
|
||||||
|
|
||||||
//save the item
|
//save the item
|
||||||
|
//NOTE: We are setting the password to NULL - this indicates to the system to not actually save the password
|
||||||
|
// so it will not get overwritten!
|
||||||
|
contentItem.PersistedContent.Password = null;
|
||||||
|
|
||||||
|
//create/save the IMember
|
||||||
Services.MemberService.Save(contentItem.PersistedContent);
|
Services.MemberService.Save(contentItem.PersistedContent);
|
||||||
|
|
||||||
//return the updated model
|
//return the updated model
|
||||||
@@ -156,6 +180,106 @@ namespace Umbraco.Web.Editors
|
|||||||
return display;
|
return display;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Maps the property values to the persisted entity
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="contentItem"></param>
|
||||||
|
private void MapPropertyValues(MemberSave contentItem)
|
||||||
|
{
|
||||||
|
UpdateName(contentItem);
|
||||||
|
|
||||||
|
//map the custom properties - this will already be set for new entities in our member binder
|
||||||
|
contentItem.PersistedContent.Email = contentItem.Email;
|
||||||
|
contentItem.PersistedContent.Username = contentItem.Username;
|
||||||
|
|
||||||
|
//use the base method to map the rest of the properties
|
||||||
|
base.MapPropertyValues(contentItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This is going to create the user with the membership provider and check for validation
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="contentItem"></param>
|
||||||
|
/// <param name="status"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
/// <remarks>
|
||||||
|
/// If this is successful, it will go and re-fetch the IMember from the db because it will now have an ID because the Umbraco provider
|
||||||
|
/// uses the umbraco data store - then of course we need to re-map it to the saved property values.
|
||||||
|
/// </remarks>
|
||||||
|
private MembershipUser CreateWithUmbracoProvider(MemberSave contentItem, out MembershipCreateStatus status)
|
||||||
|
{
|
||||||
|
//if we are creating a new one, create the member using the membership provider first
|
||||||
|
|
||||||
|
//TODO: I think we should detect if the Umbraco membership provider is active, if so then we'll create the member first and the provider key doesn't matter
|
||||||
|
// but if we are using a 3rd party membership provider - then we should create our IMember first and use it's key as their provider user key!
|
||||||
|
|
||||||
|
//NOTE: We are casting directly to the umbraco membership provider so we can specify the member type that we want to use!
|
||||||
|
|
||||||
|
var umbracoMembershipProvider = (global::umbraco.providers.members.UmbracoMembershipProvider)Membership.Provider;
|
||||||
|
var membershipUser = umbracoMembershipProvider.CreateUser(
|
||||||
|
contentItem.ContentTypeAlias, contentItem.Username, contentItem.Password, contentItem.Email, "", "", true, Guid.NewGuid(), out status);
|
||||||
|
|
||||||
|
//TODO: Localize these!
|
||||||
|
switch (status)
|
||||||
|
{
|
||||||
|
case MembershipCreateStatus.Success:
|
||||||
|
|
||||||
|
//Go and re-fetch the persisted item
|
||||||
|
contentItem.PersistedContent = Services.MemberService.GetByUsername(contentItem.Username.Trim());
|
||||||
|
//remap the values to save
|
||||||
|
MapPropertyValues(contentItem);
|
||||||
|
|
||||||
|
break;
|
||||||
|
case MembershipCreateStatus.InvalidUserName:
|
||||||
|
ModelState.AddPropertyError(
|
||||||
|
new ValidationResult("Invalid user name", new[] { "value" }),
|
||||||
|
string.Format("{0}login", Constants.PropertyEditors.InternalGenericPropertiesPrefix));
|
||||||
|
break;
|
||||||
|
case MembershipCreateStatus.InvalidPassword:
|
||||||
|
ModelState.AddPropertyError(
|
||||||
|
new ValidationResult("Invalid password", new[] { "value" }),
|
||||||
|
string.Format("{0}password", Constants.PropertyEditors.InternalGenericPropertiesPrefix));
|
||||||
|
break;
|
||||||
|
case MembershipCreateStatus.InvalidQuestion:
|
||||||
|
case MembershipCreateStatus.InvalidAnswer:
|
||||||
|
throw new NotSupportedException("Currently the member editor does not support providers that have RequiresQuestionAndAnswer specified");
|
||||||
|
case MembershipCreateStatus.InvalidEmail:
|
||||||
|
ModelState.AddPropertyError(
|
||||||
|
new ValidationResult("Invalid email", new[] { "value" }),
|
||||||
|
string.Format("{0}email", Constants.PropertyEditors.InternalGenericPropertiesPrefix));
|
||||||
|
break;
|
||||||
|
case MembershipCreateStatus.DuplicateUserName:
|
||||||
|
ModelState.AddPropertyError(
|
||||||
|
new ValidationResult("Username is already in use", new[] { "value" }),
|
||||||
|
string.Format("{0}login", Constants.PropertyEditors.InternalGenericPropertiesPrefix));
|
||||||
|
break;
|
||||||
|
case MembershipCreateStatus.DuplicateEmail:
|
||||||
|
ModelState.AddPropertyError(
|
||||||
|
new ValidationResult("Email address is already in use", new[] { "value" }),
|
||||||
|
string.Format("{0}email", Constants.PropertyEditors.InternalGenericPropertiesPrefix));
|
||||||
|
break;
|
||||||
|
case MembershipCreateStatus.InvalidProviderUserKey:
|
||||||
|
ModelState.AddPropertyError(
|
||||||
|
//specify 'default' just so that it shows up as a notification - is not assigned to a property
|
||||||
|
new ValidationResult("Invalid provider user key"), "default");
|
||||||
|
break;
|
||||||
|
case MembershipCreateStatus.DuplicateProviderUserKey:
|
||||||
|
ModelState.AddPropertyError(
|
||||||
|
//specify 'default' just so that it shows up as a notification - is not assigned to a property
|
||||||
|
new ValidationResult("Duplicate provider user key"), "default");
|
||||||
|
break;
|
||||||
|
case MembershipCreateStatus.ProviderError:
|
||||||
|
case MembershipCreateStatus.UserRejected:
|
||||||
|
ModelState.AddPropertyError(
|
||||||
|
//specify 'default' just so that it shows up as a notification - is not assigned to a property
|
||||||
|
new ValidationResult("User could not be created (rejected by provider)"), "default");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new ArgumentOutOfRangeException();
|
||||||
|
}
|
||||||
|
|
||||||
|
return membershipUser;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Permanently deletes a member
|
/// Permanently deletes a member
|
||||||
|
|||||||
@@ -0,0 +1,132 @@
|
|||||||
|
using System;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net;
|
||||||
|
using System.Web.Http;
|
||||||
|
using System.Web.Http.Controllers;
|
||||||
|
using System.Web.Http.Filters;
|
||||||
|
using System.Web.Security;
|
||||||
|
using Umbraco.Core;
|
||||||
|
using Umbraco.Web.Models.ContentEditing;
|
||||||
|
|
||||||
|
namespace Umbraco.Web.Editors
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// This validates the submitted data in regards to the current membership provider
|
||||||
|
/// </summary>
|
||||||
|
internal class MembershipProviderValidationFilterAttribute : ActionFilterAttribute
|
||||||
|
{
|
||||||
|
public override void OnActionExecuting(HttpActionContext actionContext)
|
||||||
|
{
|
||||||
|
base.OnActionExecuting(actionContext);
|
||||||
|
|
||||||
|
//default provider!
|
||||||
|
var membershipProvider = Membership.Provider;
|
||||||
|
|
||||||
|
var contentItem = (MemberSave) actionContext.ActionArguments["contentItem"];
|
||||||
|
|
||||||
|
var validEmail = ValidateUniqueEmail(contentItem, membershipProvider, actionContext);
|
||||||
|
if (validEmail == false)
|
||||||
|
{
|
||||||
|
actionContext.ModelState.AddPropertyError(
|
||||||
|
new ValidationResult("Email address is already in use", new[] {"value"}),
|
||||||
|
string.Format("{0}email", Constants.PropertyEditors.InternalGenericPropertiesPrefix));
|
||||||
|
}
|
||||||
|
|
||||||
|
var validLogin = ValidateUniqueLogin(contentItem, membershipProvider, actionContext);
|
||||||
|
if (validLogin == false)
|
||||||
|
{
|
||||||
|
actionContext.ModelState.AddPropertyError(
|
||||||
|
new ValidationResult("Username is already in use", new[] { "value" }),
|
||||||
|
string.Format("{0}login", Constants.PropertyEditors.InternalGenericPropertiesPrefix));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal bool ValidateUniqueLogin(MemberSave contentItem, MembershipProvider membershipProvider, HttpActionContext actionContext)
|
||||||
|
{
|
||||||
|
if (contentItem == null) throw new ArgumentNullException("contentItem");
|
||||||
|
if (membershipProvider == null) throw new ArgumentNullException("membershipProvider");
|
||||||
|
|
||||||
|
int totalRecs;
|
||||||
|
var existingByEmail = membershipProvider.FindUsersByName(contentItem.Username.Trim(), 0, int.MaxValue, out totalRecs);
|
||||||
|
switch (contentItem.Action)
|
||||||
|
{
|
||||||
|
case ContentSaveAction.Save:
|
||||||
|
|
||||||
|
if (contentItem.PersistedContent.Email.InvariantEquals(contentItem.Email.Trim()) == false)
|
||||||
|
{
|
||||||
|
//they are changing their login name
|
||||||
|
if (existingByEmail.Cast<MembershipUser>().Select(x => x.UserName)
|
||||||
|
.Any(x => x.InvariantEquals(contentItem.Username.Trim())))
|
||||||
|
{
|
||||||
|
//the user cannot use this login
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ContentSaveAction.SaveNew:
|
||||||
|
//check if the user's login already exists
|
||||||
|
if (existingByEmail.Cast<MembershipUser>().Select(x => x.UserName)
|
||||||
|
.Any(x => x.InvariantEquals(contentItem.Username.Trim())))
|
||||||
|
{
|
||||||
|
//the user cannot use this login
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ContentSaveAction.Publish:
|
||||||
|
case ContentSaveAction.PublishNew:
|
||||||
|
default:
|
||||||
|
//we don't support this for members
|
||||||
|
throw new HttpResponseException(HttpStatusCode.NotFound);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal bool ValidateUniqueEmail(MemberSave contentItem, MembershipProvider membershipProvider, HttpActionContext actionContext)
|
||||||
|
{
|
||||||
|
if (contentItem == null) throw new ArgumentNullException("contentItem");
|
||||||
|
if (membershipProvider == null) throw new ArgumentNullException("membershipProvider");
|
||||||
|
|
||||||
|
if (membershipProvider.RequiresUniqueEmail == false)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int totalRecs;
|
||||||
|
var existingByEmail = membershipProvider.FindUsersByEmail(contentItem.Email.Trim(), 0, int.MaxValue, out totalRecs);
|
||||||
|
switch (contentItem.Action)
|
||||||
|
{
|
||||||
|
case ContentSaveAction.Save:
|
||||||
|
//ok, we're updating the member, we need to check if they are changing their email and if so, does it exist already ?
|
||||||
|
if (contentItem.PersistedContent.Email.InvariantEquals(contentItem.Email.Trim()) == false)
|
||||||
|
{
|
||||||
|
//they are changing their email
|
||||||
|
if (existingByEmail.Cast<MembershipUser>().Select(x => x.Email)
|
||||||
|
.Any(x => x.InvariantEquals(contentItem.Email.Trim())))
|
||||||
|
{
|
||||||
|
//the user cannot use this email
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ContentSaveAction.SaveNew:
|
||||||
|
//check if the user's email already exists
|
||||||
|
if (existingByEmail.Cast<MembershipUser>().Select(x => x.Email)
|
||||||
|
.Any(x => x.InvariantEquals(contentItem.Email.Trim())))
|
||||||
|
{
|
||||||
|
//the user cannot use this email
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ContentSaveAction.Publish:
|
||||||
|
case ContentSaveAction.PublishNew:
|
||||||
|
default:
|
||||||
|
//we don't support this for members
|
||||||
|
throw new HttpResponseException(HttpStatusCode.NotFound);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Web.Mvc;
|
using System.Web.Mvc;
|
||||||
|
|
||||||
@@ -48,6 +49,32 @@ namespace Umbraco.Web
|
|||||||
// state.AddModelError("DataValidation", errorMessage);
|
// state.AddModelError("DataValidation", errorMessage);
|
||||||
//}
|
//}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds the error to model state correctly for a property so we can use it on the client side.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="modelState"></param>
|
||||||
|
/// <param name="result"></param>
|
||||||
|
/// <param name="propertyAlias"></param>
|
||||||
|
internal static void AddPropertyError(this System.Web.Http.ModelBinding.ModelStateDictionary modelState, ValidationResult result, string propertyAlias)
|
||||||
|
{
|
||||||
|
//if there are no member names supplied then we assume that the validation message is for the overall property
|
||||||
|
// not a sub field on the property editor
|
||||||
|
if (!result.MemberNames.Any())
|
||||||
|
{
|
||||||
|
//add a model state error for the entire property
|
||||||
|
modelState.AddModelError(string.Format("{0}.{1}", "Properties", propertyAlias), result.ErrorMessage);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//there's assigned field names so we'll combine the field name with the property name
|
||||||
|
// so that we can try to match it up to a real sub field of this editor
|
||||||
|
foreach (var field in result.MemberNames)
|
||||||
|
{
|
||||||
|
modelState.AddModelError(string.Format("{0}.{1}.{2}", "Properties", propertyAlias, field), result.ErrorMessage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static IDictionary<string, object> ToErrorDictionary(this System.Web.Http.ModelBinding.ModelStateDictionary modelState)
|
public static IDictionary<string, object> ToErrorDictionary(this System.Web.Http.ModelBinding.ModelStateDictionary modelState)
|
||||||
{
|
{
|
||||||
var modelStateError = new Dictionary<string, object>();
|
var modelStateError = new Dictionary<string, object>();
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System.Runtime.Serialization;
|
using System;
|
||||||
|
using System.Runtime.Serialization;
|
||||||
using Umbraco.Core.Models;
|
using Umbraco.Core.Models;
|
||||||
|
|
||||||
namespace Umbraco.Web.Models.ContentEditing
|
namespace Umbraco.Web.Models.ContentEditing
|
||||||
@@ -16,5 +17,11 @@ namespace Umbraco.Web.Models.ContentEditing
|
|||||||
[DataMember(Name = "email")]
|
[DataMember(Name = "email")]
|
||||||
public string Email { get; set; }
|
public string Email { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This is the unique Id stored in the database - but could also be the unique id for a custom membership provider
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(Name = "key")]
|
||||||
|
public Guid Key { get; set; }
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
using AutoMapper;
|
using System.Collections.Generic;
|
||||||
|
using AutoMapper;
|
||||||
using Umbraco.Core;
|
using Umbraco.Core;
|
||||||
using Umbraco.Core.Models;
|
using Umbraco.Core.Models;
|
||||||
using Umbraco.Core.Models.Mapping;
|
using Umbraco.Core.Models.Mapping;
|
||||||
@@ -53,7 +54,9 @@ namespace Umbraco.Web.Models.Mapping
|
|||||||
config.CreateMap<IMember, ContentItemDto<IMember>>()
|
config.CreateMap<IMember, ContentItemDto<IMember>>()
|
||||||
.ForMember(
|
.ForMember(
|
||||||
dto => dto.Owner,
|
dto => dto.Owner,
|
||||||
expression => expression.ResolveUsing<OwnerResolver<IMember>>());
|
expression => expression.ResolveUsing<OwnerResolver<IMember>>())
|
||||||
|
//do no map the custom member properties (currently anyways, they were never there in 6.x)
|
||||||
|
.ForMember(dto => dto.Properties, expression => expression.ResolveUsing<MemberDtoPropertiesValueResolver>());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -70,7 +73,8 @@ namespace Umbraco.Web.Models.Mapping
|
|||||||
Alias = string.Format("{0}login", Constants.PropertyEditors.InternalGenericPropertiesPrefix),
|
Alias = string.Format("{0}login", Constants.PropertyEditors.InternalGenericPropertiesPrefix),
|
||||||
Label = ui.Text("login"),
|
Label = ui.Text("login"),
|
||||||
Value = display.Username,
|
Value = display.Username,
|
||||||
View = "textbox"
|
View = "textbox",
|
||||||
|
Config = new Dictionary<string, object> { { "IsRequired", true } }
|
||||||
},
|
},
|
||||||
new ContentPropertyDisplay
|
new ContentPropertyDisplay
|
||||||
{
|
{
|
||||||
@@ -84,10 +88,28 @@ namespace Umbraco.Web.Models.Mapping
|
|||||||
Alias = string.Format("{0}email", Constants.PropertyEditors.InternalGenericPropertiesPrefix),
|
Alias = string.Format("{0}email", Constants.PropertyEditors.InternalGenericPropertiesPrefix),
|
||||||
Label = ui.Text("general", "email"),
|
Label = ui.Text("general", "email"),
|
||||||
Value = display.Email,
|
Value = display.Email,
|
||||||
View = "textbox"
|
View = "email",
|
||||||
|
Config = new Dictionary<string, object> {{"IsRequired", true}}
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This ensures that the custom membership provider properties are not mapped (currently since they weren't there in v6)
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Because these properties don't exist on the form, if we don't remove them for this map we'll get validation errors when posting data
|
||||||
|
/// </remarks>
|
||||||
|
internal class MemberDtoPropertiesValueResolver : ValueResolver<IMember, IEnumerable<ContentPropertyDto>>
|
||||||
|
{
|
||||||
|
protected override IEnumerable<ContentPropertyDto> ResolveCore(IMember source)
|
||||||
|
{
|
||||||
|
var exclude = Constants.Conventions.Member.StandardPropertyTypeStubs.Select(x => x.Value.Alias).ToArray();
|
||||||
|
return source.Properties
|
||||||
|
.Where(x => exclude.Contains(x.Alias) == false)
|
||||||
|
.Select(Mapper.Map<Property, ContentPropertyDto>);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
using Umbraco.Core;
|
||||||
|
using Umbraco.Core.PropertyEditors;
|
||||||
|
|
||||||
|
namespace Umbraco.Web.PropertyEditors
|
||||||
|
{
|
||||||
|
[PropertyEditor(Constants.PropertyEditors.EmailAddressAlias, "Email address", "email")]
|
||||||
|
public class EmailAddressPropertyEditor : PropertyEditor
|
||||||
|
{
|
||||||
|
protected override PropertyValueEditor CreateValueEditor()
|
||||||
|
{
|
||||||
|
var editor = base.CreateValueEditor();
|
||||||
|
//add an email address validator
|
||||||
|
editor.Validators.Add(new EmailValidator());
|
||||||
|
return editor;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override PreValueEditor CreatePreValueEditor()
|
||||||
|
{
|
||||||
|
return new EmailAddressePreValueEditor();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class EmailAddressePreValueEditor : PreValueEditor
|
||||||
|
{
|
||||||
|
[PreValueField("Required?", "boolean")]
|
||||||
|
public bool IsRequired { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Specialized;
|
using System.Collections.Specialized;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
using System.Configuration.Provider;
|
using System.Configuration.Provider;
|
||||||
|
using System.Linq;
|
||||||
using System.Security.Cryptography;
|
using System.Security.Cryptography;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
@@ -8,6 +10,7 @@ using System.Web.Hosting;
|
|||||||
using System.Web.Security;
|
using System.Web.Security;
|
||||||
using Umbraco.Core;
|
using Umbraco.Core;
|
||||||
using Umbraco.Core.Logging;
|
using Umbraco.Core.Logging;
|
||||||
|
using Umbraco.Core.Models;
|
||||||
using Umbraco.Core.Services;
|
using Umbraco.Core.Services;
|
||||||
using Umbraco.Core.Models.Membership;
|
using Umbraco.Core.Models.Membership;
|
||||||
|
|
||||||
@@ -254,8 +257,9 @@ namespace Umbraco.Web.Security.Providers
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Adds a new membership user to the data source.
|
/// Adds a new membership user to the data source with the specified member type
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <param name="memberType">A specific member type to create the member for</param>
|
||||||
/// <param name="username">The user name for the new user.</param>
|
/// <param name="username">The user name for the new user.</param>
|
||||||
/// <param name="password">The password for the new user.</param>
|
/// <param name="password">The password for the new user.</param>
|
||||||
/// <param name="email">The e-mail address for the new user.</param>
|
/// <param name="email">The e-mail address for the new user.</param>
|
||||||
@@ -267,16 +271,16 @@ namespace Umbraco.Web.Security.Providers
|
|||||||
/// <returns>
|
/// <returns>
|
||||||
/// A <see cref="T:System.Web.Security.MembershipUser"></see> object populated with the information for the newly created user.
|
/// A <see cref="T:System.Web.Security.MembershipUser"></see> object populated with the information for the newly created user.
|
||||||
/// </returns>
|
/// </returns>
|
||||||
public override MembershipUser CreateUser(string username, string password, string email, string passwordQuestion, string passwordAnswer,
|
public MembershipUser CreateUser(string memberType, string username, string password, string email, string passwordQuestion, string passwordAnswer,
|
||||||
bool isApproved, object providerUserKey, out MembershipCreateStatus status)
|
bool isApproved, object providerUserKey, out MembershipCreateStatus status)
|
||||||
{
|
{
|
||||||
LogHelper.Debug<MembersMembershipProvider>("Member signup requested: username -> " + username + ". email -> " +email);
|
LogHelper.Debug<MembersMembershipProvider>("Member signup requested: username -> " + username + ". email -> " + email);
|
||||||
|
|
||||||
// Validate password
|
// Validate password
|
||||||
if (IsPasswordValid(password) == false)
|
if (IsPasswordValid(password) == false)
|
||||||
{
|
{
|
||||||
status = MembershipCreateStatus.InvalidPassword;
|
status = MembershipCreateStatus.InvalidPassword;
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate email
|
// Validate email
|
||||||
@@ -324,18 +328,41 @@ namespace Umbraco.Web.Security.Providers
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
var member = MemberService.CreateMember(email, username, password, DefaultMemberTypeAlias);
|
var member = MemberService.CreateMember(email, username, password, memberType);
|
||||||
|
|
||||||
member.IsApproved = isApproved;
|
member.IsApproved = isApproved;
|
||||||
member.PasswordQuestion = passwordQuestion;
|
member.PasswordQuestion = passwordQuestion;
|
||||||
member.PasswordAnswer = passwordAnswer;
|
member.PasswordAnswer = passwordAnswer;
|
||||||
|
|
||||||
|
//encrypts/hashes the password depending on the settings
|
||||||
|
member.Password = EncryptOrHashPassword(member.Password);
|
||||||
|
|
||||||
MemberService.Save(member);
|
MemberService.Save(member);
|
||||||
|
|
||||||
status = MembershipCreateStatus.Success;
|
status = MembershipCreateStatus.Success;
|
||||||
return member.AsConcreteMembershipUser();
|
return member.AsConcreteMembershipUser();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds a new membership user to the data source.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="username">The user name for the new user.</param>
|
||||||
|
/// <param name="password">The password for the new user.</param>
|
||||||
|
/// <param name="email">The e-mail address for the new user.</param>
|
||||||
|
/// <param name="passwordQuestion">The password question for the new user.</param>
|
||||||
|
/// <param name="passwordAnswer">The password answer for the new user</param>
|
||||||
|
/// <param name="isApproved">Whether or not the new user is approved to be validated.</param>
|
||||||
|
/// <param name="providerUserKey">The unique identifier from the membership data source for the user.</param>
|
||||||
|
/// <param name="status">A <see cref="T:System.Web.Security.MembershipCreateStatus"></see> enumeration value indicating whether the user was created successfully.</param>
|
||||||
|
/// <returns>
|
||||||
|
/// A <see cref="T:System.Web.Security.MembershipUser"></see> object populated with the information for the newly created user.
|
||||||
|
/// </returns>
|
||||||
|
public override MembershipUser CreateUser(string username, string password, string email, string passwordQuestion, string passwordAnswer,
|
||||||
|
bool isApproved, object providerUserKey, out MembershipCreateStatus status)
|
||||||
|
{
|
||||||
|
return CreateUser(DefaultMemberTypeAlias, username, password, email, passwordQuestion, passwordAnswer, isApproved, providerUserKey, out status);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Processes a request to update the password question and answer for a membership user.
|
/// Processes a request to update the password question and answer for a membership user.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -360,7 +387,7 @@ namespace Umbraco.Web.Security.Providers
|
|||||||
}
|
}
|
||||||
|
|
||||||
var member = MemberService.GetByUsername(username);
|
var member = MemberService.GetByUsername(username);
|
||||||
var encodedPassword = EncodePassword(password);
|
var encodedPassword = EncryptOrHashPassword(password);
|
||||||
|
|
||||||
if (member.Password == encodedPassword)
|
if (member.Password == encodedPassword)
|
||||||
{
|
{
|
||||||
@@ -427,12 +454,12 @@ namespace Umbraco.Web.Security.Providers
|
|||||||
var member = MemberService.GetByUsername(username);
|
var member = MemberService.GetByUsername(username);
|
||||||
if (member == null) return false;
|
if (member == null) return false;
|
||||||
|
|
||||||
var encodedPassword = EncodePassword(oldPassword);
|
var encodedPassword = EncryptOrHashPassword(oldPassword);
|
||||||
|
|
||||||
if (member.Password == encodedPassword)
|
if (member.Password == encodedPassword)
|
||||||
{
|
{
|
||||||
|
|
||||||
member.Password = EncodePassword(newPassword);
|
member.Password = EncryptOrHashPassword(newPassword);
|
||||||
MemberService.Save(member);
|
MemberService.Save(member);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -464,7 +491,7 @@ namespace Umbraco.Web.Security.Providers
|
|||||||
if (_requiresQuestionAndAnswer == false || (_requiresQuestionAndAnswer && answer == member.PasswordAnswer))
|
if (_requiresQuestionAndAnswer == false || (_requiresQuestionAndAnswer && answer == member.PasswordAnswer))
|
||||||
{
|
{
|
||||||
member.Password =
|
member.Password =
|
||||||
EncodePassword(Membership.GeneratePassword(_minRequiredPasswordLength,
|
EncryptOrHashPassword(Membership.GeneratePassword(_minRequiredPasswordLength,
|
||||||
_minRequiredNonAlphanumericCharacters));
|
_minRequiredNonAlphanumericCharacters));
|
||||||
MemberService.Save(member);
|
MemberService.Save(member);
|
||||||
}
|
}
|
||||||
@@ -505,7 +532,7 @@ namespace Umbraco.Web.Security.Providers
|
|||||||
if (member.IsLockedOut)
|
if (member.IsLockedOut)
|
||||||
throw new ProviderException("The member is locked out.");
|
throw new ProviderException("The member is locked out.");
|
||||||
|
|
||||||
var encodedPassword = EncodePassword(password);
|
var encodedPassword = EncryptOrHashPassword(password);
|
||||||
|
|
||||||
var authenticated = (encodedPassword == member.Password);
|
var authenticated = (encodedPassword == member.Password);
|
||||||
|
|
||||||
@@ -687,7 +714,16 @@ namespace Umbraco.Web.Security.Providers
|
|||||||
/// </returns>
|
/// </returns>
|
||||||
public override MembershipUserCollection FindUsersByEmail(string emailToMatch, int pageIndex, int pageSize, out int totalRecords)
|
public override MembershipUserCollection FindUsersByEmail(string emailToMatch, int pageIndex, int pageSize, out int totalRecords)
|
||||||
{
|
{
|
||||||
throw new System.NotImplementedException();
|
var byEmail = MemberService.FindMembersByEmail(emailToMatch).ToArray();
|
||||||
|
totalRecords = byEmail.Length;
|
||||||
|
var pagedResult = new PagedResult<IMember>(totalRecords, pageIndex, pageSize);
|
||||||
|
|
||||||
|
var collection = new MembershipUserCollection();
|
||||||
|
foreach (var m in byEmail.Skip(pagedResult.SkipSize).Take(pageSize))
|
||||||
|
{
|
||||||
|
collection.Add(m.AsConcreteMembershipUser());
|
||||||
|
}
|
||||||
|
return collection;
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Private methods
|
#region Private methods
|
||||||
@@ -714,11 +750,9 @@ namespace Umbraco.Web.Security.Providers
|
|||||||
|
|
||||||
private bool IsEmaiValid(string email)
|
private bool IsEmaiValid(string email)
|
||||||
{
|
{
|
||||||
const string pattern = @"^(?!\.)(""([^""\r\\]|\\[""\r\\])*""|"
|
var validator = new EmailAddressAttribute();
|
||||||
+ @"([-a-z0-9!#$%&'*+/=?^_`{|}~]|(?<!\.)\.)*)(?<!\.)"
|
|
||||||
+ @"@[a-z0-9][\w\.-]*[a-z0-9]\.[a-z][a-z\.]*[a-z]$";
|
|
||||||
|
|
||||||
return Regex.IsMatch(email, pattern, RegexOptions.IgnoreCase | RegexOptions.Compiled);
|
return validator.IsValid(email);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -726,7 +760,7 @@ namespace Umbraco.Web.Security.Providers
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="password">The password.</param>
|
/// <param name="password">The password.</param>
|
||||||
/// <returns>The encoded password.</returns>
|
/// <returns>The encoded password.</returns>
|
||||||
private string EncodePassword(string password)
|
private string EncryptOrHashPassword(string password)
|
||||||
{
|
{
|
||||||
var encodedPassword = password;
|
var encodedPassword = password;
|
||||||
switch (PasswordFormat)
|
switch (PasswordFormat)
|
||||||
|
|||||||
@@ -309,6 +309,7 @@
|
|||||||
<Compile Include="Editors\DataTypeValidateAttribute.cs" />
|
<Compile Include="Editors\DataTypeValidateAttribute.cs" />
|
||||||
<Compile Include="Editors\LogController.cs" />
|
<Compile Include="Editors\LogController.cs" />
|
||||||
<Compile Include="Editors\MacroController.cs" />
|
<Compile Include="Editors\MacroController.cs" />
|
||||||
|
<Compile Include="Editors\MembershipProviderValidationFilterAttribute.cs" />
|
||||||
<Compile Include="Editors\MemberTypeController.cs" />
|
<Compile Include="Editors\MemberTypeController.cs" />
|
||||||
<Compile Include="Models\ContentEditing\StyleSheet.cs" />
|
<Compile Include="Models\ContentEditing\StyleSheet.cs" />
|
||||||
<Compile Include="Editors\StylesheetController.cs" />
|
<Compile Include="Editors\StylesheetController.cs" />
|
||||||
@@ -327,6 +328,7 @@
|
|||||||
<Compile Include="Models\Mapping\MacroModelMapper.cs" />
|
<Compile Include="Models\Mapping\MacroModelMapper.cs" />
|
||||||
<Compile Include="Models\Mapping\MemberModelMapper.cs" />
|
<Compile Include="Models\Mapping\MemberModelMapper.cs" />
|
||||||
<Compile Include="PropertyEditors\ColorListPreValueEditor.cs" />
|
<Compile Include="PropertyEditors\ColorListPreValueEditor.cs" />
|
||||||
|
<Compile Include="PropertyEditors\EmailAddressPropertyEditor.cs" />
|
||||||
<Compile Include="PropertyEditors\ListViewPropertyEditor.cs" />
|
<Compile Include="PropertyEditors\ListViewPropertyEditor.cs" />
|
||||||
<Compile Include="PropertyEditors\MemberPickerPropertyEditor.cs" />
|
<Compile Include="PropertyEditors\MemberPickerPropertyEditor.cs" />
|
||||||
<Compile Include="PropertyEditors\ParameterEditors\TextAreaParameterEditor.cs" />
|
<Compile Include="PropertyEditors\ParameterEditors\TextAreaParameterEditor.cs" />
|
||||||
@@ -352,7 +354,6 @@
|
|||||||
<Compile Include="Models\Mapping\DataTypeModelMapper.cs" />
|
<Compile Include="Models\Mapping\DataTypeModelMapper.cs" />
|
||||||
<Compile Include="Models\Mapping\EntityModelMapper.cs" />
|
<Compile Include="Models\Mapping\EntityModelMapper.cs" />
|
||||||
<Compile Include="Models\Mapping\PreValueDisplayResolver.cs" />
|
<Compile Include="Models\Mapping\PreValueDisplayResolver.cs" />
|
||||||
<Compile Include="Models\PagedResult.cs" />
|
|
||||||
<Compile Include="PropertyEditors\CheckBoxListPropertyEditor.cs" />
|
<Compile Include="PropertyEditors\CheckBoxListPropertyEditor.cs" />
|
||||||
<Compile Include="PropertyEditors\ColorPickerPropertyEditor.cs" />
|
<Compile Include="PropertyEditors\ColorPickerPropertyEditor.cs" />
|
||||||
<Compile Include="PropertyEditors\DatePropertyEditor.cs" />
|
<Compile Include="PropertyEditors\DatePropertyEditor.cs" />
|
||||||
|
|||||||
@@ -25,7 +25,8 @@ namespace Umbraco.Web.WebApi.Binders
|
|||||||
|
|
||||||
protected override IMember GetExisting(MemberSave model)
|
protected override IMember GetExisting(MemberSave model)
|
||||||
{
|
{
|
||||||
//TODO: We're going to remove the built-in member properties from this editor - not sure if we should be persisting them elsewhere ?
|
//TODO: We're going to remove the built-in member properties from this editor - We didn't support these in 6.x so
|
||||||
|
// pretty hard to support them in 7 when the member type editor is using the old APIs!
|
||||||
var toRemove = Constants.Conventions.Member.StandardPropertyTypeStubs.Select(x => x.Value.Alias).ToArray();
|
var toRemove = Constants.Conventions.Member.StandardPropertyTypeStubs.Select(x => x.Value.Alias).ToArray();
|
||||||
|
|
||||||
var member = ApplicationContext.Services.MemberService.GetByUsername(model.Username);
|
var member = ApplicationContext.Services.MemberService.GetByUsername(model.Username);
|
||||||
@@ -38,11 +39,21 @@ namespace Umbraco.Web.WebApi.Binders
|
|||||||
|
|
||||||
protected override IMember CreateNew(MemberSave model)
|
protected override IMember CreateNew(MemberSave model)
|
||||||
{
|
{
|
||||||
var contentType = ApplicationContext.Services.ContentTypeService.GetMemberType(model.ContentTypeAlias);
|
var contentType = ApplicationContext.Services.MemberTypeService.GetMemberType(model.ContentTypeAlias);
|
||||||
if (contentType == null)
|
if (contentType == null)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("No member type found wth alias " + model.ContentTypeAlias);
|
throw new InvalidOperationException("No member type found wth alias " + model.ContentTypeAlias);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO: We're going to remove the built-in member properties from this editor - We didn't support these in 6.x so
|
||||||
|
// pretty hard to support them in 7 when the member type editor is using the old APIs!
|
||||||
|
var toRemove = Constants.Conventions.Member.StandardPropertyTypeStubs.Select(x => x.Value.Alias).ToArray();
|
||||||
|
foreach (var remove in toRemove)
|
||||||
|
{
|
||||||
|
contentType.RemovePropertyType(remove);
|
||||||
|
}
|
||||||
|
|
||||||
|
//return the new member with the details filled in
|
||||||
return new Member(model.Name, model.Email, model.Username, model.Password, -1, contentType);
|
return new Member(model.Name, model.Email, model.Username, model.Password, -1, contentType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -139,7 +139,7 @@ namespace Umbraco.Web.WebApi.Filters
|
|||||||
|
|
||||||
foreach (var result in editor.ValueEditor.Validators.SelectMany(v => v.Validate(postedValue, preValues, editor)))
|
foreach (var result in editor.ValueEditor.Validators.SelectMany(v => v.Validate(postedValue, preValues, editor)))
|
||||||
{
|
{
|
||||||
AddError(actionContext.ModelState, result, p.Alias);
|
actionContext.ModelState.AddPropertyError(result, p.Alias);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Now we need to validate the property based on the PropertyType validation (i.e. regex and required)
|
//Now we need to validate the property based on the PropertyType validation (i.e. regex and required)
|
||||||
@@ -148,7 +148,7 @@ namespace Umbraco.Web.WebApi.Filters
|
|||||||
{
|
{
|
||||||
foreach (var result in p.PropertyEditor.ValueEditor.RequiredValidator.Validate(postedValue, "", preValues, editor))
|
foreach (var result in p.PropertyEditor.ValueEditor.RequiredValidator.Validate(postedValue, "", preValues, editor))
|
||||||
{
|
{
|
||||||
AddError(actionContext.ModelState, result, p.Alias);
|
actionContext.ModelState.AddPropertyError(result, p.Alias);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -156,7 +156,7 @@ namespace Umbraco.Web.WebApi.Filters
|
|||||||
{
|
{
|
||||||
foreach (var result in p.PropertyEditor.ValueEditor.RegexValidator.Validate(postedValue, p.ValidationRegExp, preValues, editor))
|
foreach (var result in p.PropertyEditor.ValueEditor.RegexValidator.Validate(postedValue, p.ValidationRegExp, preValues, editor))
|
||||||
{
|
{
|
||||||
AddError(actionContext.ModelState, result, p.Alias);
|
actionContext.ModelState.AddPropertyError(result, p.Alias);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -164,30 +164,6 @@ namespace Umbraco.Web.WebApi.Filters
|
|||||||
return actionContext.ModelState.IsValid;
|
return actionContext.ModelState.IsValid;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Adds the error to model state correctly for a property so we can use it on the client side.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="modelState"></param>
|
|
||||||
/// <param name="result"></param>
|
|
||||||
/// <param name="propertyAlias"></param>
|
|
||||||
private void AddError(ModelStateDictionary modelState, ValidationResult result, string propertyAlias)
|
|
||||||
{
|
|
||||||
//if there are no member names supplied then we assume that the validation message is for the overall property
|
|
||||||
// not a sub field on the property editor
|
|
||||||
if (!result.MemberNames.Any())
|
|
||||||
{
|
|
||||||
//add a model state error for the entire property
|
|
||||||
modelState.AddModelError(string.Format("{0}.{1}", "Properties", propertyAlias), result.ErrorMessage);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//there's assigned field names so we'll combine the field name with the property name
|
|
||||||
// so that we can try to match it up to a real sub field of this editor
|
|
||||||
foreach (var field in result.MemberNames)
|
|
||||||
{
|
|
||||||
modelState.AddModelError(string.Format("{0}.{1}.{2}", "Properties", propertyAlias, field), result.ErrorMessage);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -31,8 +31,8 @@ namespace umbraco.cms.businesslogic.member
|
|||||||
public class Member : Content
|
public class Member : Content
|
||||||
{
|
{
|
||||||
#region Constants and static members
|
#region Constants and static members
|
||||||
public static readonly string UmbracoMemberProviderName = "UmbracoMembershipProvider";
|
public static readonly string UmbracoMemberProviderName = Constants.Conventions.Member.UmbracoMemberProviderName;
|
||||||
public static readonly string UmbracoRoleProviderName = "UmbracoRoleProvider";
|
public static readonly string UmbracoRoleProviderName = Constants.Conventions.Member.UmbracoRoleProviderName;
|
||||||
public static readonly Guid _objectType = new Guid(Constants.ObjectTypes.Member);
|
public static readonly Guid _objectType = new Guid(Constants.ObjectTypes.Member);
|
||||||
|
|
||||||
private static readonly object m_Locker = new object();
|
private static readonly object m_Locker = new object();
|
||||||
@@ -212,6 +212,8 @@ namespace umbraco.cms.businesslogic.member
|
|||||||
/// <returns>The new member</returns>
|
/// <returns>The new member</returns>
|
||||||
public static Member MakeNew(string Name, string LoginName, string Email, MemberType mbt, User u)
|
public static Member MakeNew(string Name, string LoginName, string Email, MemberType mbt, User u)
|
||||||
{
|
{
|
||||||
|
if (mbt == null) throw new ArgumentNullException("mbt");
|
||||||
|
|
||||||
var loginName = (!String.IsNullOrEmpty(LoginName)) ? LoginName : Name;
|
var loginName = (!String.IsNullOrEmpty(LoginName)) ? LoginName : Name;
|
||||||
|
|
||||||
if (String.IsNullOrEmpty(loginName))
|
if (String.IsNullOrEmpty(loginName))
|
||||||
|
|||||||
@@ -815,7 +815,7 @@ namespace umbraco.cms.businesslogic.web
|
|||||||
|
|
||||||
if (!e.Cancel)
|
if (!e.Cancel)
|
||||||
{
|
{
|
||||||
var result = ((ContentService)ApplicationContext.Current.Services.ContentService).PublishInternal(Content, u.Id);
|
var result = ApplicationContext.Current.Services.ContentService.PublishWithStatus(Content, u.Id);
|
||||||
_published = result.Success;
|
_published = result.Success;
|
||||||
|
|
||||||
FireAfterPublish(e);
|
FireAfterPublish(e);
|
||||||
@@ -831,8 +831,7 @@ namespace umbraco.cms.businesslogic.web
|
|||||||
[Obsolete("Obsolete, Use Umbraco.Core.Services.ContentService.PublishWithChildren()", false)]
|
[Obsolete("Obsolete, Use Umbraco.Core.Services.ContentService.PublishWithChildren()", false)]
|
||||||
public bool PublishWithChildrenWithResult(User u)
|
public bool PublishWithChildrenWithResult(User u)
|
||||||
{
|
{
|
||||||
var result = ((ContentService)ApplicationContext.Current.Services.ContentService)
|
var result = ApplicationContext.Current.Services.ContentService.PublishWithChildrenWithStatus(Content, u.Id, true);
|
||||||
.PublishWithChildrenInternal(Content, u.Id, true);
|
|
||||||
//This used to just return false only when the parent content failed, otherwise would always return true so we'll
|
//This used to just return false only when the parent content failed, otherwise would always return true so we'll
|
||||||
// do the same thing for the moment
|
// do the same thing for the moment
|
||||||
return result.Single(x => x.Result.ContentItem.Id == Id).Success;
|
return result.Single(x => x.Result.ContentItem.Id == Id).Success;
|
||||||
@@ -872,8 +871,8 @@ namespace umbraco.cms.businesslogic.web
|
|||||||
|
|
||||||
if (!e.Cancel)
|
if (!e.Cancel)
|
||||||
{
|
{
|
||||||
IEnumerable<Attempt<PublishStatus>> publishedResults = ((ContentService)ApplicationContext.Current.Services.ContentService)
|
IEnumerable<Attempt<PublishStatus>> publishedResults = ApplicationContext.Current.Services.ContentService
|
||||||
.PublishWithChildrenInternal(Content, u.Id);
|
.PublishWithChildrenWithStatus(Content, u.Id);
|
||||||
|
|
||||||
FireAfterPublish(e);
|
FireAfterPublish(e);
|
||||||
}
|
}
|
||||||
@@ -889,8 +888,8 @@ namespace umbraco.cms.businesslogic.web
|
|||||||
|
|
||||||
if (!e.Cancel)
|
if (!e.Cancel)
|
||||||
{
|
{
|
||||||
publishedResults = ((ContentService) ApplicationContext.Current.Services.ContentService)
|
publishedResults = ApplicationContext.Current.Services.ContentService
|
||||||
.PublishWithChildrenInternal(Content, userId, includeUnpublished);
|
.PublishWithChildrenWithStatus(Content, userId, includeUnpublished);
|
||||||
|
|
||||||
FireAfterPublish(e);
|
FireAfterPublish(e);
|
||||||
}
|
}
|
||||||
@@ -918,8 +917,8 @@ namespace umbraco.cms.businesslogic.web
|
|||||||
if (!publishArgs.Cancel)
|
if (!publishArgs.Cancel)
|
||||||
{
|
{
|
||||||
//NOTE: The 'false' parameter will cause the PublishingStrategy events to fire which will ensure that the cache is refreshed.
|
//NOTE: The 'false' parameter will cause the PublishingStrategy events to fire which will ensure that the cache is refreshed.
|
||||||
result = ((ContentService)ApplicationContext.Current.Services.ContentService)
|
result = ApplicationContext.Current.Services.ContentService
|
||||||
.SaveAndPublishInternal(Content, userId);
|
.SaveAndPublishWithStatus(Content, userId);
|
||||||
base.VersionDate = Content.UpdateDate;
|
base.VersionDate = Content.UpdateDate;
|
||||||
this.UpdateDate = Content.UpdateDate;
|
this.UpdateDate = Content.UpdateDate;
|
||||||
|
|
||||||
@@ -1007,8 +1006,8 @@ namespace umbraco.cms.businesslogic.web
|
|||||||
if (!publishArgs.Cancel)
|
if (!publishArgs.Cancel)
|
||||||
{
|
{
|
||||||
//NOTE: The 'false' parameter will cause the PublishingStrategy events to fire which will ensure that the cache is refreshed.
|
//NOTE: The 'false' parameter will cause the PublishingStrategy events to fire which will ensure that the cache is refreshed.
|
||||||
var result = ((ContentService)ApplicationContext.Current.Services.ContentService)
|
var result = ApplicationContext.Current.Services.ContentService
|
||||||
.SaveAndPublishInternal(Content, u.Id);
|
.SaveAndPublishWithStatus(Content, u.Id);
|
||||||
base.VersionDate = Content.UpdateDate;
|
base.VersionDate = Content.UpdateDate;
|
||||||
this.UpdateDate = Content.UpdateDate;
|
this.UpdateDate = Content.UpdateDate;
|
||||||
|
|
||||||
|
|||||||
@@ -1,20 +1,24 @@
|
|||||||
#region namespace
|
#region namespace
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Web.Security;
|
using System.Web.Security;
|
||||||
using System.Configuration;
|
using System.Configuration;
|
||||||
|
using Umbraco.Core;
|
||||||
|
using Umbraco.Core.Models;
|
||||||
using umbraco.BusinessLogic;
|
using umbraco.BusinessLogic;
|
||||||
using System.Security.Cryptography;
|
using System.Security.Cryptography;
|
||||||
using System.Web.Util;
|
using System.Web.Util;
|
||||||
using System.Collections.Specialized;
|
using System.Collections.Specialized;
|
||||||
using System.Configuration.Provider;
|
using System.Configuration.Provider;
|
||||||
using umbraco.cms.businesslogic;
|
using umbraco.cms.businesslogic;
|
||||||
using umbraco.cms.businesslogic.member;
|
|
||||||
|
|
||||||
using System.Security;
|
using System.Security;
|
||||||
using System.Security.Permissions;
|
using System.Security.Permissions;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
using Member = umbraco.cms.businesslogic.member.Member;
|
||||||
|
using MemberType = umbraco.cms.businesslogic.member.MemberType;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
namespace umbraco.providers.members
|
namespace umbraco.providers.members
|
||||||
@@ -354,6 +358,68 @@ namespace umbraco.providers.members
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds a new membership user to the data source.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="memberTypeAlias"></param>
|
||||||
|
/// <param name="username">The user name for the new user.</param>
|
||||||
|
/// <param name="password">The password for the new user.</param>
|
||||||
|
/// <param name="email">The e-mail address for the new user.</param>
|
||||||
|
/// <param name="passwordQuestion">The password question for the new user.</param>
|
||||||
|
/// <param name="passwordAnswer">The password answer for the new user</param>
|
||||||
|
/// <param name="isApproved">Whether or not the new user is approved to be validated.</param>
|
||||||
|
/// <param name="providerUserKey">The unique identifier from the membership data source for the user.</param>
|
||||||
|
/// <param name="status">A <see cref="T:System.Web.Security.MembershipCreateStatus"></see> enumeration value indicating whether the user was created successfully.</param>
|
||||||
|
/// <returns>
|
||||||
|
/// A <see cref="T:System.Web.Security.MembershipUser"></see> object populated with the information for the newly created user.
|
||||||
|
/// </returns>
|
||||||
|
public MembershipUser CreateUser(string memberTypeAlias, string username, string password, string email, string passwordQuestion,
|
||||||
|
string passwordAnswer, bool isApproved, object providerUserKey, out MembershipCreateStatus status)
|
||||||
|
{
|
||||||
|
if (Member.GetMemberFromLoginName(username) != null)
|
||||||
|
status = MembershipCreateStatus.DuplicateUserName;
|
||||||
|
else if (Member.GetMemberFromEmail(email) != null && RequiresUniqueEmail)
|
||||||
|
status = MembershipCreateStatus.DuplicateEmail;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var memberType = MemberType.GetByAlias(memberTypeAlias);
|
||||||
|
if (memberType == null)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Could not find a member type with alias " + memberTypeAlias + ". Ensure your membership provider configuration is up to date and that the default member type exists.");
|
||||||
|
}
|
||||||
|
|
||||||
|
Member m = Member.MakeNew(username, email, memberType, User.GetUser(0));
|
||||||
|
m.Password = password;
|
||||||
|
|
||||||
|
MembershipUser mUser =
|
||||||
|
ConvertToMembershipUser(m);
|
||||||
|
|
||||||
|
// custom fields
|
||||||
|
if (!String.IsNullOrEmpty(m_PasswordRetrievalQuestionPropertyTypeAlias))
|
||||||
|
UpdateMemberProperty(m, m_PasswordRetrievalQuestionPropertyTypeAlias, passwordQuestion);
|
||||||
|
|
||||||
|
if (!String.IsNullOrEmpty(m_PasswordRetrievalAnswerPropertyTypeAlias))
|
||||||
|
UpdateMemberProperty(m, m_PasswordRetrievalAnswerPropertyTypeAlias, passwordAnswer);
|
||||||
|
|
||||||
|
if (!String.IsNullOrEmpty(m_ApprovedPropertyTypeAlias))
|
||||||
|
UpdateMemberProperty(m, m_ApprovedPropertyTypeAlias, isApproved);
|
||||||
|
|
||||||
|
if (!String.IsNullOrEmpty(m_LastLoginPropertyTypeAlias))
|
||||||
|
{
|
||||||
|
mUser.LastActivityDate = DateTime.Now;
|
||||||
|
UpdateMemberProperty(m, m_LastLoginPropertyTypeAlias, mUser.LastActivityDate);
|
||||||
|
}
|
||||||
|
|
||||||
|
// save
|
||||||
|
m.Save();
|
||||||
|
|
||||||
|
status = MembershipCreateStatus.Success;
|
||||||
|
|
||||||
|
return mUser;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Adds a new membership user to the data source.
|
/// Adds a new membership user to the data source.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -371,41 +437,7 @@ namespace umbraco.providers.members
|
|||||||
public override MembershipUser CreateUser(string username, string password, string email, string passwordQuestion,
|
public override MembershipUser CreateUser(string username, string password, string email, string passwordQuestion,
|
||||||
string passwordAnswer, bool isApproved, object providerUserKey, out MembershipCreateStatus status)
|
string passwordAnswer, bool isApproved, object providerUserKey, out MembershipCreateStatus status)
|
||||||
{
|
{
|
||||||
if (Member.GetMemberFromLoginName(username) != null)
|
return CreateUser(m_DefaultMemberTypeAlias, username, password, email, passwordQuestion, passwordAnswer, isApproved, providerUserKey, out status);
|
||||||
status = MembershipCreateStatus.DuplicateUserName;
|
|
||||||
else if (Member.GetMemberFromEmail(email) != null && RequiresUniqueEmail)
|
|
||||||
status = MembershipCreateStatus.DuplicateEmail;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Member m = Member.MakeNew(username, email, MemberType.GetByAlias(m_DefaultMemberTypeAlias), User.GetUser(0));
|
|
||||||
m.Password = password;
|
|
||||||
|
|
||||||
MembershipUser mUser =
|
|
||||||
ConvertToMembershipUser(m);
|
|
||||||
|
|
||||||
// custom fields
|
|
||||||
if (!String.IsNullOrEmpty(m_PasswordRetrievalQuestionPropertyTypeAlias))
|
|
||||||
UpdateMemberProperty(m, m_PasswordRetrievalQuestionPropertyTypeAlias, passwordQuestion);
|
|
||||||
|
|
||||||
if (!String.IsNullOrEmpty(m_PasswordRetrievalAnswerPropertyTypeAlias))
|
|
||||||
UpdateMemberProperty(m, m_PasswordRetrievalAnswerPropertyTypeAlias, passwordAnswer);
|
|
||||||
|
|
||||||
if (!String.IsNullOrEmpty(m_ApprovedPropertyTypeAlias))
|
|
||||||
UpdateMemberProperty(m, m_ApprovedPropertyTypeAlias, isApproved);
|
|
||||||
|
|
||||||
if (!String.IsNullOrEmpty(m_LastLoginPropertyTypeAlias)) {
|
|
||||||
mUser.LastActivityDate = DateTime.Now;
|
|
||||||
UpdateMemberProperty(m, m_LastLoginPropertyTypeAlias, mUser.LastActivityDate);
|
|
||||||
}
|
|
||||||
|
|
||||||
// save
|
|
||||||
m.Save();
|
|
||||||
|
|
||||||
status = MembershipCreateStatus.Success;
|
|
||||||
|
|
||||||
return mUser;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -439,7 +471,16 @@ namespace umbraco.providers.members
|
|||||||
/// </returns>
|
/// </returns>
|
||||||
public override MembershipUserCollection FindUsersByEmail(string emailToMatch, int pageIndex, int pageSize, out int totalRecords)
|
public override MembershipUserCollection FindUsersByEmail(string emailToMatch, int pageIndex, int pageSize, out int totalRecords)
|
||||||
{
|
{
|
||||||
throw new Exception("The method or operation is not implemented.");
|
var byEmail = ApplicationContext.Current.Services.MemberService.FindMembersByEmail(emailToMatch).ToArray();
|
||||||
|
totalRecords = byEmail.Length;
|
||||||
|
var pagedResult = new PagedResult<IMember>(totalRecords, pageIndex, pageSize);
|
||||||
|
|
||||||
|
var collection = new MembershipUserCollection();
|
||||||
|
foreach (var m in byEmail.Skip(pagedResult.SkipSize).Take(pageSize))
|
||||||
|
{
|
||||||
|
collection.Add(ConvertToMembershipUser(m));
|
||||||
|
}
|
||||||
|
return collection;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -752,6 +793,26 @@ namespace umbraco.providers.members
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static string GetMemberProperty(IMember m, string propertyAlias, bool isBool)
|
||||||
|
{
|
||||||
|
if (!String.IsNullOrEmpty(propertyAlias))
|
||||||
|
{
|
||||||
|
if (m.Properties[propertyAlias] != null &&
|
||||||
|
m.Properties[propertyAlias].Value != null)
|
||||||
|
{
|
||||||
|
if (isBool)
|
||||||
|
{
|
||||||
|
// Umbraco stored true as 1, which means it can be bool.tryParse'd
|
||||||
|
return m.Properties[propertyAlias].Value.ToString().Replace("1", "true").Replace("0", "false");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return m.Properties[propertyAlias].Value.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Verifies that the specified user name and password exist in the data source.
|
/// Verifies that the specified user name and password exist in the data source.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -973,6 +1034,53 @@ namespace umbraco.providers.members
|
|||||||
DateTime.Now, DateTime.Now, DateTime.Now);
|
DateTime.Now, DateTime.Now, DateTime.Now);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Converts to membership user.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="m">The m.</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
private MembershipUser ConvertToMembershipUser(IMember m)
|
||||||
|
{
|
||||||
|
if (m == null) return null;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DateTime lastLogin = DateTime.Now;
|
||||||
|
bool isApproved = true;
|
||||||
|
bool isLocked = false;
|
||||||
|
string comment = "";
|
||||||
|
string passwordQuestion = "";
|
||||||
|
|
||||||
|
// last login
|
||||||
|
if (!String.IsNullOrEmpty(m_LastLoginPropertyTypeAlias))
|
||||||
|
{
|
||||||
|
DateTime.TryParse(GetMemberProperty(m, m_LastLoginPropertyTypeAlias, false), out lastLogin);
|
||||||
|
}
|
||||||
|
// approved
|
||||||
|
if (!String.IsNullOrEmpty(m_ApprovedPropertyTypeAlias))
|
||||||
|
{
|
||||||
|
bool.TryParse(GetMemberProperty(m, m_ApprovedPropertyTypeAlias, true), out isApproved);
|
||||||
|
}
|
||||||
|
// locked
|
||||||
|
if (!String.IsNullOrEmpty(m_LockPropertyTypeAlias))
|
||||||
|
{
|
||||||
|
bool.TryParse(GetMemberProperty(m, m_LockPropertyTypeAlias, true), out isLocked);
|
||||||
|
}
|
||||||
|
// comment
|
||||||
|
if (!String.IsNullOrEmpty(m_CommentPropertyTypeAlias))
|
||||||
|
{
|
||||||
|
comment = GetMemberProperty(m, m_CommentPropertyTypeAlias, false);
|
||||||
|
}
|
||||||
|
// password question
|
||||||
|
if (!String.IsNullOrEmpty(m_PasswordRetrievalQuestionPropertyTypeAlias))
|
||||||
|
{
|
||||||
|
passwordQuestion = GetMemberProperty(m, m_PasswordRetrievalQuestionPropertyTypeAlias, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new MembershipUser(m_providerName, m.Username, m.Id, m.Email, passwordQuestion, comment, isApproved, isLocked, m.CreateDate, lastLogin,
|
||||||
|
DateTime.Now, DateTime.Now, DateTime.Now);
|
||||||
|
}
|
||||||
|
}
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -99,6 +99,10 @@
|
|||||||
<Project>{ccd75ec3-63db-4184-b49d-51c1dd337230}</Project>
|
<Project>{ccd75ec3-63db-4184-b49d-51c1dd337230}</Project>
|
||||||
<Name>umbraco.cms</Name>
|
<Name>umbraco.cms</Name>
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
|
<ProjectReference Include="..\Umbraco.Core\Umbraco.Core.csproj">
|
||||||
|
<Project>{31785bc3-256c-4613-b2f5-a1b0bdded8c1}</Project>
|
||||||
|
<Name>Umbraco.Core</Name>
|
||||||
|
</ProjectReference>
|
||||||
<ProjectReference Include="..\umbraco.datalayer\umbraco.datalayer.csproj">
|
<ProjectReference Include="..\umbraco.datalayer\umbraco.datalayer.csproj">
|
||||||
<Project>{C7CB79F0-1C97-4B33-BFA7-00731B579AE2}</Project>
|
<Project>{C7CB79F0-1C97-4B33-BFA7-00731B579AE2}</Project>
|
||||||
<Name>umbraco.datalayer</Name>
|
<Name>umbraco.datalayer</Name>
|
||||||
|
|||||||
Reference in New Issue
Block a user