PageRenderTime 34ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/src/Orchard.Azure/Orchard.Azure.Web/Modules/Orchard.Users/Services/MembershipService.cs

http://associativy.codeplex.com
C# | 226 lines | 175 code | 47 blank | 4 comment | 34 complexity | 58c0b5dc296cddac48d0ef2c79dabf2f MD5 | raw file
Possible License(s): LGPL-2.1, MIT, BSD-3-Clause, Apache-2.0, CPL-1.0, CC-BY-SA-3.0, GPL-2.0
  1. using System;
  2. using System.Linq;
  3. using System.Security.Cryptography;
  4. using System.Text;
  5. using System.Web.Security;
  6. using JetBrains.Annotations;
  7. using Orchard.Localization;
  8. using Orchard.Logging;
  9. using Orchard.ContentManagement;
  10. using Orchard.Security;
  11. using Orchard.Users.Events;
  12. using Orchard.Users.Models;
  13. using Orchard.Messaging.Services;
  14. using System.Collections.Generic;
  15. using Orchard.Services;
  16. namespace Orchard.Users.Services {
  17. [UsedImplicitly]
  18. public class MembershipService : IMembershipService {
  19. private readonly IOrchardServices _orchardServices;
  20. private readonly IMessageManager _messageManager;
  21. private readonly IEnumerable<IUserEventHandler> _userEventHandlers;
  22. private readonly IEncryptionService _encryptionService;
  23. public MembershipService(IOrchardServices orchardServices, IMessageManager messageManager, IEnumerable<IUserEventHandler> userEventHandlers, IClock clock, IEncryptionService encryptionService) {
  24. _orchardServices = orchardServices;
  25. _messageManager = messageManager;
  26. _userEventHandlers = userEventHandlers;
  27. _encryptionService = encryptionService;
  28. Logger = NullLogger.Instance;
  29. T = NullLocalizer.Instance;
  30. }
  31. public ILogger Logger { get; set; }
  32. public Localizer T { get; set; }
  33. public MembershipSettings GetSettings() {
  34. var settings = new MembershipSettings();
  35. // accepting defaults
  36. return settings;
  37. }
  38. public IUser CreateUser(CreateUserParams createUserParams) {
  39. Logger.Information("CreateUser {0} {1}", createUserParams.Username, createUserParams.Email);
  40. var registrationSettings = _orchardServices.WorkContext.CurrentSite.As<RegistrationSettingsPart>();
  41. var user = _orchardServices.ContentManager.New<UserPart>("User");
  42. user.Record.UserName = createUserParams.Username;
  43. user.Record.Email = createUserParams.Email;
  44. user.Record.NormalizedUserName = createUserParams.Username.ToLowerInvariant();
  45. user.Record.HashAlgorithm = "SHA1";
  46. SetPassword(user.Record, createUserParams.Password);
  47. if ( registrationSettings != null ) {
  48. user.Record.RegistrationStatus = registrationSettings.UsersAreModerated ? UserStatus.Pending : UserStatus.Approved;
  49. user.Record.EmailStatus = registrationSettings.UsersMustValidateEmail ? UserStatus.Pending : UserStatus.Approved;
  50. }
  51. if(createUserParams.IsApproved) {
  52. user.Record.RegistrationStatus = UserStatus.Approved;
  53. user.Record.EmailStatus = UserStatus.Approved;
  54. }
  55. var userContext = new UserContext {User = user, Cancel = false, UserParameters = createUserParams};
  56. foreach(var userEventHandler in _userEventHandlers) {
  57. userEventHandler.Creating(userContext);
  58. }
  59. if(userContext.Cancel) {
  60. return null;
  61. }
  62. _orchardServices.ContentManager.Create(user);
  63. foreach ( var userEventHandler in _userEventHandlers ) {
  64. userEventHandler.Created(userContext);
  65. if (user.RegistrationStatus == UserStatus.Approved) {
  66. userEventHandler.Approved(user);
  67. }
  68. }
  69. if ( registrationSettings != null && registrationSettings.UsersAreModerated && registrationSettings.NotifyModeration && !createUserParams.IsApproved ) {
  70. var usernames = String.IsNullOrWhiteSpace(registrationSettings.NotificationsRecipients)
  71. ? new string[0]
  72. : registrationSettings.NotificationsRecipients.Split(new[] {',', ' '}, StringSplitOptions.RemoveEmptyEntries);
  73. foreach ( var userName in usernames ) {
  74. if (String.IsNullOrWhiteSpace(userName)) {
  75. continue;
  76. }
  77. var recipient = GetUser(userName);
  78. if (recipient != null)
  79. _messageManager.Send(recipient.ContentItem.Record, MessageTypes.Moderation, "email" , new Dictionary<string, string> { { "UserName", createUserParams.Username}, { "Email" , createUserParams.Email } });
  80. }
  81. }
  82. return user;
  83. }
  84. public IUser GetUser(string username) {
  85. var lowerName = username == null ? "" : username.ToLowerInvariant();
  86. return _orchardServices.ContentManager.Query<UserPart, UserPartRecord>().Where(u => u.NormalizedUserName == lowerName).List().FirstOrDefault();
  87. }
  88. public IUser ValidateUser(string userNameOrEmail, string password) {
  89. var lowerName = userNameOrEmail == null ? "" : userNameOrEmail.ToLowerInvariant();
  90. var user = _orchardServices.ContentManager.Query<UserPart, UserPartRecord>().Where(u => u.NormalizedUserName == lowerName).List().FirstOrDefault();
  91. if (user == null)
  92. user = _orchardServices.ContentManager.Query<UserPart, UserPartRecord>().Where(u => u.Email == lowerName).List().FirstOrDefault();
  93. if ( user == null || ValidatePassword(user.As<UserPart>().Record, password) == false )
  94. return null;
  95. if ( user.EmailStatus != UserStatus.Approved )
  96. return null;
  97. if ( user.RegistrationStatus != UserStatus.Approved )
  98. return null;
  99. return user;
  100. }
  101. public void SetPassword(IUser user, string password) {
  102. if (!user.Is<UserPart>())
  103. throw new InvalidCastException();
  104. var userRecord = user.As<UserPart>().Record;
  105. SetPassword(userRecord, password);
  106. }
  107. void SetPassword(UserPartRecord partRecord, string password) {
  108. switch (GetSettings().PasswordFormat) {
  109. case MembershipPasswordFormat.Clear:
  110. SetPasswordClear(partRecord, password);
  111. break;
  112. case MembershipPasswordFormat.Hashed:
  113. SetPasswordHashed(partRecord, password);
  114. break;
  115. case MembershipPasswordFormat.Encrypted:
  116. SetPasswordEncrypted(partRecord, password);
  117. break;
  118. default:
  119. throw new ApplicationException(T("Unexpected password format value").ToString());
  120. }
  121. }
  122. private bool ValidatePassword(UserPartRecord partRecord, string password) {
  123. // Note - the password format stored with the record is used
  124. // otherwise changing the password format on the site would invalidate
  125. // all logins
  126. switch (partRecord.PasswordFormat) {
  127. case MembershipPasswordFormat.Clear:
  128. return ValidatePasswordClear(partRecord, password);
  129. case MembershipPasswordFormat.Hashed:
  130. return ValidatePasswordHashed(partRecord, password);
  131. case MembershipPasswordFormat.Encrypted:
  132. return ValidatePasswordEncrypted(partRecord, password);
  133. default:
  134. throw new ApplicationException("Unexpected password format value");
  135. }
  136. }
  137. private static void SetPasswordClear(UserPartRecord partRecord, string password) {
  138. partRecord.PasswordFormat = MembershipPasswordFormat.Clear;
  139. partRecord.Password = password;
  140. partRecord.PasswordSalt = null;
  141. }
  142. private static bool ValidatePasswordClear(UserPartRecord partRecord, string password) {
  143. return partRecord.Password == password;
  144. }
  145. private static void SetPasswordHashed(UserPartRecord partRecord, string password) {
  146. var saltBytes = new byte[0x10];
  147. using (var random = new RNGCryptoServiceProvider()) {
  148. random.GetBytes(saltBytes);
  149. }
  150. var passwordBytes = Encoding.Unicode.GetBytes(password);
  151. var combinedBytes = saltBytes.Concat(passwordBytes).ToArray();
  152. byte[] hashBytes;
  153. using (var hashAlgorithm = HashAlgorithm.Create(partRecord.HashAlgorithm)) {
  154. hashBytes = hashAlgorithm.ComputeHash(combinedBytes);
  155. }
  156. partRecord.PasswordFormat = MembershipPasswordFormat.Hashed;
  157. partRecord.Password = Convert.ToBase64String(hashBytes);
  158. partRecord.PasswordSalt = Convert.ToBase64String(saltBytes);
  159. }
  160. private static bool ValidatePasswordHashed(UserPartRecord partRecord, string password) {
  161. var saltBytes = Convert.FromBase64String(partRecord.PasswordSalt);
  162. var passwordBytes = Encoding.Unicode.GetBytes(password);
  163. var combinedBytes = saltBytes.Concat(passwordBytes).ToArray();
  164. byte[] hashBytes;
  165. using (var hashAlgorithm = HashAlgorithm.Create(partRecord.HashAlgorithm)) {
  166. hashBytes = hashAlgorithm.ComputeHash(combinedBytes);
  167. }
  168. return partRecord.Password == Convert.ToBase64String(hashBytes);
  169. }
  170. private void SetPasswordEncrypted(UserPartRecord partRecord, string password) {
  171. partRecord.Password = Convert.ToBase64String(_encryptionService.Encode(Encoding.UTF8.GetBytes(password)));
  172. partRecord.PasswordSalt = null;
  173. partRecord.PasswordFormat = MembershipPasswordFormat.Encrypted;
  174. }
  175. private bool ValidatePasswordEncrypted(UserPartRecord partRecord, string password) {
  176. return String.Equals(password, Encoding.UTF8.GetString(_encryptionService.Decode(Convert.FromBase64String(partRecord.Password))), StringComparison.Ordinal);
  177. }
  178. }
  179. }