PageRenderTime 61ms CodeModel.GetById 28ms RepoModel.GetById 1ms app.codeStats 0ms

/src/Umbraco.Core/Services/MemberService.cs

https://github.com/ekolicic/Umbraco-CMS
C# | 1258 lines | 893 code | 139 blank | 226 comment | 86 complexity | 5368dd5e2ed2e1488f4b34523a56466e MD5 | raw file
Possible License(s): MIT, BSD-3-Clause

Large files files are truncated, but you can click here to view the full file

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Runtime.CompilerServices;
  4. using System.Threading;
  5. using System.Web.Security;
  6. using System.Xml.Linq;
  7. using System.Xml.Linq;
  8. using Umbraco.Core.Auditing;
  9. using Umbraco.Core.Configuration;
  10. using Umbraco.Core.Events;
  11. using Umbraco.Core.Events;
  12. using Umbraco.Core.Models;
  13. using Umbraco.Core.Models.EntityBase;
  14. using Umbraco.Core.Models.Membership;
  15. using Umbraco.Core.Models.Rdbms;
  16. using Umbraco.Core.Persistence;
  17. using Umbraco.Core.Persistence.Querying;
  18. using Umbraco.Core.Persistence.Repositories;
  19. using Umbraco.Core.Persistence.SqlSyntax;
  20. using Umbraco.Core.Persistence.UnitOfWork;
  21. using System.Linq;
  22. using Umbraco.Core.Security;
  23. namespace Umbraco.Core.Services
  24. {
  25. /// <summary>
  26. /// Represents the MemberService.
  27. /// </summary>
  28. public class MemberService : IMemberService
  29. {
  30. private readonly RepositoryFactory _repositoryFactory;
  31. private readonly IMemberGroupService _memberGroupService;
  32. private readonly IDatabaseUnitOfWorkProvider _uowProvider;
  33. private readonly EntityXmlSerializer _entitySerializer = new EntityXmlSerializer();
  34. private readonly IDataTypeService _dataTypeService;
  35. private static readonly ReaderWriterLockSlim Locker = new ReaderWriterLockSlim();
  36. public MemberService(RepositoryFactory repositoryFactory, IMemberGroupService memberGroupService)
  37. : this(new PetaPocoUnitOfWorkProvider(), repositoryFactory, memberGroupService)
  38. {
  39. }
  40. public MemberService(IDatabaseUnitOfWorkProvider provider, IMemberGroupService memberGroupService)
  41. : this(provider, new RepositoryFactory(), memberGroupService)
  42. {
  43. }
  44. public MemberService(IDatabaseUnitOfWorkProvider provider, RepositoryFactory repositoryFactory, IMemberGroupService memberGroupService)
  45. {
  46. if (provider == null) throw new ArgumentNullException("provider");
  47. if (repositoryFactory == null) throw new ArgumentNullException("repositoryFactory");
  48. if (memberGroupService == null) throw new ArgumentNullException("memberGroupService");
  49. _repositoryFactory = repositoryFactory;
  50. _memberGroupService = memberGroupService;
  51. _uowProvider = provider;
  52. _dataTypeService = new DataTypeService(provider, repositoryFactory);
  53. }
  54. public MemberService(IDatabaseUnitOfWorkProvider provider, IMemberGroupService memberGroupService, IDataTypeService dataTypeService)
  55. : this(provider, new RepositoryFactory(), memberGroupService, dataTypeService)
  56. {
  57. }
  58. public MemberService(IDatabaseUnitOfWorkProvider provider, RepositoryFactory repositoryFactory, IMemberGroupService memberGroupService, IDataTypeService dataTypeService)
  59. {
  60. if (provider == null) throw new ArgumentNullException("provider");
  61. if (repositoryFactory == null) throw new ArgumentNullException("repositoryFactory");
  62. if (memberGroupService == null) throw new ArgumentNullException("memberGroupService");
  63. _repositoryFactory = repositoryFactory;
  64. _memberGroupService = memberGroupService;
  65. _uowProvider = provider;
  66. _dataTypeService = dataTypeService;
  67. }
  68. #region IMemberService Implementation
  69. /// <summary>
  70. /// Get the default member type from the database - first check if the type "Member" is there, if not choose the first one found
  71. /// </summary>
  72. /// <returns></returns>
  73. public string GetDefaultMemberType()
  74. {
  75. using (var repository = _repositoryFactory.CreateMemberTypeRepository(_uowProvider.GetUnitOfWork()))
  76. {
  77. var types = repository.GetAll().Select(x => x.Alias).ToArray();
  78. if (types.Any() == false)
  79. {
  80. throw new InvalidOperationException("No member types could be resolved");
  81. }
  82. if (types.InvariantContains("Member"))
  83. {
  84. return types.First(x => x.InvariantEquals("Member"));
  85. }
  86. return types.First();
  87. }
  88. }
  89. /// <summary>
  90. /// Checks if a member with the username exists
  91. /// </summary>
  92. /// <param name="username"></param>
  93. /// <returns></returns>
  94. public bool Exists(string username)
  95. {
  96. using (var repository = _repositoryFactory.CreateMemberRepository(_uowProvider.GetUnitOfWork()))
  97. {
  98. return repository.Exists(username);
  99. }
  100. }
  101. /// <summary>
  102. /// This is simply a helper method which essentially just wraps the MembershipProvider's ChangePassword method
  103. /// </summary>
  104. /// <param name="member">The member to save the password for</param>
  105. /// <param name="password"></param>
  106. /// <remarks>
  107. /// This method exists so that Umbraco developers can use one entry point to create/update members if they choose to.
  108. /// </remarks>
  109. public void SavePassword(IMember member, string password)
  110. {
  111. if (member == null) throw new ArgumentNullException("member");
  112. var provider = MembershipProviderExtensions.GetMembersMembershipProvider();
  113. if (provider.IsUmbracoMembershipProvider())
  114. {
  115. provider.ChangePassword(member.Username, "", password);
  116. }
  117. else
  118. {
  119. throw new NotSupportedException("When using a non-Umbraco membership provider you must change the member password by using the MembershipProvider.ChangePassword method");
  120. }
  121. //go re-fetch the member and update the properties that may have changed
  122. var result = GetByUsername(member.Username);
  123. //should never be null but it could have been deleted by another thread.
  124. if (result == null)
  125. return;
  126. member.RawPasswordValue = result.RawPasswordValue;
  127. member.LastPasswordChangeDate = result.LastPasswordChangeDate;
  128. member.UpdateDate = member.UpdateDate;
  129. }
  130. /// <summary>
  131. /// Checks if a member with the id exists
  132. /// </summary>
  133. /// <param name="id"></param>
  134. /// <returns></returns>
  135. public bool Exists(int id)
  136. {
  137. using (var repository = _repositoryFactory.CreateMemberRepository(_uowProvider.GetUnitOfWork()))
  138. {
  139. return repository.Exists(id);
  140. }
  141. }
  142. /// <summary>
  143. /// Gets a Member by its integer Id
  144. /// </summary>
  145. /// <param name="id"></param>
  146. /// <returns></returns>
  147. public IMember GetById(int id)
  148. {
  149. using (var repository = _repositoryFactory.CreateMemberRepository(_uowProvider.GetUnitOfWork()))
  150. {
  151. return repository.Get(id);
  152. }
  153. }
  154. /// <summary>
  155. /// Gets a Member by its Guid key
  156. /// </summary>
  157. /// <remarks>
  158. /// The guid key corresponds to the unique id in the database
  159. /// and the user id in the membership provider.
  160. /// </remarks>
  161. /// <param name="id"></param>
  162. /// <returns></returns>
  163. public IMember GetByKey(Guid id)
  164. {
  165. using (var repository = _repositoryFactory.CreateMemberRepository(_uowProvider.GetUnitOfWork()))
  166. {
  167. var query = Query<IMember>.Builder.Where(x => x.Key == id);
  168. var member = repository.GetByQuery(query).FirstOrDefault();
  169. return member;
  170. }
  171. }
  172. /// <summary>
  173. /// Gets a list of Members by their MemberType
  174. /// </summary>
  175. /// <param name="memberTypeAlias"></param>
  176. /// <returns></returns>
  177. public IEnumerable<IMember> GetMembersByMemberType(string memberTypeAlias)
  178. {
  179. using (var repository = _repositoryFactory.CreateMemberRepository(_uowProvider.GetUnitOfWork()))
  180. {
  181. var query = Query<IMember>.Builder.Where(x => x.ContentTypeAlias == memberTypeAlias);
  182. var members = repository.GetByQuery(query);
  183. return members;
  184. }
  185. }
  186. /// <summary>
  187. /// Gets a list of Members by their MemberType
  188. /// </summary>
  189. /// <param name="memberTypeId"></param>
  190. /// <returns></returns>
  191. public IEnumerable<IMember> GetMembersByMemberType(int memberTypeId)
  192. {
  193. using (var repository = _repositoryFactory.CreateMemberRepository(_uowProvider.GetUnitOfWork()))
  194. {
  195. repository.Get(memberTypeId);
  196. var query = Query<IMember>.Builder.Where(x => x.ContentTypeId == memberTypeId);
  197. var members = repository.GetByQuery(query);
  198. return members;
  199. }
  200. }
  201. /// <summary>
  202. /// Gets a list of Members by the MemberGroup they are part of
  203. /// </summary>
  204. /// <param name="memberGroupName"></param>
  205. /// <returns></returns>
  206. public IEnumerable<IMember> GetMembersByGroup(string memberGroupName)
  207. {
  208. using (var repository = _repositoryFactory.CreateMemberRepository(_uowProvider.GetUnitOfWork()))
  209. {
  210. return repository.GetByMemberGroup(memberGroupName);
  211. }
  212. }
  213. /// <summary>
  214. /// Gets a list of all Members
  215. /// </summary>
  216. /// <param name="ids"></param>
  217. /// <returns></returns>
  218. public IEnumerable<IMember> GetAllMembers(params int[] ids)
  219. {
  220. using (var repository = _repositoryFactory.CreateMemberRepository(_uowProvider.GetUnitOfWork()))
  221. {
  222. return repository.GetAll(ids);
  223. }
  224. }
  225. public void DeleteMembersOfType(int memberTypeId)
  226. {
  227. using (new WriteLock(Locker))
  228. {
  229. using (var uow = _uowProvider.GetUnitOfWork())
  230. {
  231. var repository = _repositoryFactory.CreateMemberRepository(uow);
  232. //TODO: What about content that has the contenttype as part of its composition?
  233. var query = Query<IMember>.Builder.Where(x => x.ContentTypeId == memberTypeId);
  234. var members = repository.GetByQuery(query).ToArray();
  235. if (Deleting.IsRaisedEventCancelled(new DeleteEventArgs<IMember>(members), this))
  236. return;
  237. foreach (var member in members)
  238. {
  239. //Permantly delete the member
  240. Delete(member);
  241. }
  242. }
  243. }
  244. }
  245. public IEnumerable<IMember> FindMembersByDisplayName(string displayNameToMatch, int pageIndex, int pageSize, out int totalRecords, StringPropertyMatchType matchType = StringPropertyMatchType.StartsWith)
  246. {
  247. var uow = _uowProvider.GetUnitOfWork();
  248. using (var repository = _repositoryFactory.CreateMemberRepository(uow))
  249. {
  250. var sql = new Sql()
  251. .Select("*")
  252. .From<NodeDto>()
  253. .Where<NodeDto>(dto => dto.NodeObjectType == new Guid(Constants.ObjectTypes.Member));
  254. switch (matchType)
  255. {
  256. case StringPropertyMatchType.Exact:
  257. sql.Where<NodeDto>(dto => dto.Text.Equals(displayNameToMatch));
  258. break;
  259. case StringPropertyMatchType.Contains:
  260. sql.Where<NodeDto>(dto => dto.Text.Contains(displayNameToMatch));
  261. break;
  262. case StringPropertyMatchType.StartsWith:
  263. sql.Where<NodeDto>(dto => dto.Text.StartsWith(displayNameToMatch));
  264. break;
  265. case StringPropertyMatchType.EndsWith:
  266. sql.Where<NodeDto>(dto => dto.Text.EndsWith(displayNameToMatch));
  267. break;
  268. case StringPropertyMatchType.Wildcard:
  269. sql.Where<NodeDto>(dto => dto.Text.SqlWildcard(displayNameToMatch, TextColumnType.NVarchar));
  270. break;
  271. default:
  272. throw new ArgumentOutOfRangeException("matchType");
  273. }
  274. sql.OrderBy<NodeDto>(dto => dto.Text);
  275. var result = repository.GetPagedResultsByQuery<NodeDto>(sql, pageIndex, pageSize, out totalRecords,
  276. dtos => dtos.Select(x => x.NodeId).ToArray());
  277. //ensure this result is sorted correct just in case
  278. return result.OrderBy(x => x.Name);
  279. }
  280. }
  281. /// <summary>
  282. /// Does a search for members that contain the specified string in their email address
  283. /// </summary>
  284. /// <param name="emailStringToMatch"></param>
  285. /// <param name="totalRecords"></param>
  286. /// <param name="matchType"></param>
  287. /// <param name="pageIndex"></param>
  288. /// <param name="pageSize"></param>
  289. /// <returns></returns>
  290. public IEnumerable<IMember> FindByEmail(string emailStringToMatch, int pageIndex, int pageSize, out int totalRecords, StringPropertyMatchType matchType = StringPropertyMatchType.StartsWith)
  291. {
  292. var uow = _uowProvider.GetUnitOfWork();
  293. using (var repository = _repositoryFactory.CreateMemberRepository(uow))
  294. {
  295. var query = new Query<IMember>();
  296. switch (matchType)
  297. {
  298. case StringPropertyMatchType.Exact:
  299. query.Where(member => member.Email.Equals(emailStringToMatch));
  300. break;
  301. case StringPropertyMatchType.Contains:
  302. query.Where(member => member.Email.Contains(emailStringToMatch));
  303. break;
  304. case StringPropertyMatchType.StartsWith:
  305. query.Where(member => member.Email.StartsWith(emailStringToMatch));
  306. break;
  307. case StringPropertyMatchType.EndsWith:
  308. query.Where(member => member.Email.EndsWith(emailStringToMatch));
  309. break;
  310. case StringPropertyMatchType.Wildcard:
  311. query.Where(member => member.Email.SqlWildcard(emailStringToMatch, TextColumnType.NVarchar));
  312. break;
  313. default:
  314. throw new ArgumentOutOfRangeException("matchType");
  315. }
  316. return repository.GetPagedResultsByQuery(query, pageIndex, pageSize, out totalRecords, dto => dto.Email);
  317. }
  318. }
  319. public IEnumerable<IMember> FindByUsername(string login, int pageIndex, int pageSize, out int totalRecords, StringPropertyMatchType matchType = StringPropertyMatchType.StartsWith)
  320. {
  321. var uow = _uowProvider.GetUnitOfWork();
  322. using (var repository = _repositoryFactory.CreateMemberRepository(uow))
  323. {
  324. var query = new Query<IMember>();
  325. switch (matchType)
  326. {
  327. case StringPropertyMatchType.Exact:
  328. query.Where(member => member.Username.Equals(login));
  329. break;
  330. case StringPropertyMatchType.Contains:
  331. query.Where(member => member.Username.Contains(login));
  332. break;
  333. case StringPropertyMatchType.StartsWith:
  334. query.Where(member => member.Username.StartsWith(login));
  335. break;
  336. case StringPropertyMatchType.EndsWith:
  337. query.Where(member => member.Username.EndsWith(login));
  338. break;
  339. case StringPropertyMatchType.Wildcard:
  340. query.Where(member => member.Email.SqlWildcard(login, TextColumnType.NVarchar));
  341. break;
  342. default:
  343. throw new ArgumentOutOfRangeException("matchType");
  344. }
  345. return repository.GetPagedResultsByQuery(query, pageIndex, pageSize, out totalRecords, dto => dto.Username);
  346. }
  347. }
  348. /// <summary>
  349. /// Gets a list of Members with a certain string property value
  350. /// </summary>
  351. /// <param name="propertyTypeAlias"></param>
  352. /// <param name="value"></param>
  353. /// <param name="matchType"></param>
  354. /// <returns></returns>
  355. public IEnumerable<IMember> GetMembersByPropertyValue(string propertyTypeAlias, string value, StringPropertyMatchType matchType = StringPropertyMatchType.Exact)
  356. {
  357. using (var repository = _repositoryFactory.CreateMemberRepository(_uowProvider.GetUnitOfWork()))
  358. {
  359. IQuery<IMember> query;
  360. switch (matchType)
  361. {
  362. case StringPropertyMatchType.Exact:
  363. query =
  364. Query<IMember>.Builder.Where(
  365. x =>
  366. ((Member)x).PropertyTypeAlias == propertyTypeAlias &&
  367. (((Member)x).LongStringPropertyValue.SqlEquals(value, TextColumnType.NText) ||
  368. ((Member)x).ShortStringPropertyValue.SqlEquals(value, TextColumnType.NVarchar)));
  369. break;
  370. case StringPropertyMatchType.Contains:
  371. query =
  372. Query<IMember>.Builder.Where(
  373. x =>
  374. ((Member)x).PropertyTypeAlias == propertyTypeAlias &&
  375. (((Member)x).LongStringPropertyValue.SqlContains(value, TextColumnType.NText) ||
  376. ((Member)x).ShortStringPropertyValue.SqlContains(value, TextColumnType.NVarchar)));
  377. break;
  378. case StringPropertyMatchType.StartsWith:
  379. query =
  380. Query<IMember>.Builder.Where(
  381. x =>
  382. ((Member)x).PropertyTypeAlias == propertyTypeAlias &&
  383. (((Member)x).LongStringPropertyValue.SqlStartsWith(value, TextColumnType.NText) ||
  384. ((Member)x).ShortStringPropertyValue.SqlStartsWith(value, TextColumnType.NVarchar)));
  385. break;
  386. case StringPropertyMatchType.EndsWith:
  387. query =
  388. Query<IMember>.Builder.Where(
  389. x =>
  390. ((Member)x).PropertyTypeAlias == propertyTypeAlias &&
  391. (((Member)x).LongStringPropertyValue.SqlEndsWith(value, TextColumnType.NText) ||
  392. ((Member)x).ShortStringPropertyValue.SqlEndsWith(value, TextColumnType.NVarchar)));
  393. break;
  394. default:
  395. throw new ArgumentOutOfRangeException("matchType");
  396. }
  397. var members = repository.GetByQuery(query);
  398. return members;
  399. }
  400. }
  401. /// <summary>
  402. /// Gets a list of Members with a certain integer property value
  403. /// </summary>
  404. /// <param name="propertyTypeAlias"></param>
  405. /// <param name="value"></param>
  406. /// <param name="matchType"></param>
  407. /// <returns></returns>
  408. public IEnumerable<IMember> GetMembersByPropertyValue(string propertyTypeAlias, int value, ValuePropertyMatchType matchType = ValuePropertyMatchType.Exact)
  409. {
  410. using (var repository = _repositoryFactory.CreateMemberRepository(_uowProvider.GetUnitOfWork()))
  411. {
  412. IQuery<IMember> query;
  413. switch (matchType)
  414. {
  415. case ValuePropertyMatchType.Exact:
  416. query =
  417. Query<IMember>.Builder.Where(
  418. x =>
  419. ((Member)x).PropertyTypeAlias == propertyTypeAlias &&
  420. ((Member)x).IntegerropertyValue == value);
  421. break;
  422. case ValuePropertyMatchType.GreaterThan:
  423. query =
  424. Query<IMember>.Builder.Where(
  425. x =>
  426. ((Member)x).PropertyTypeAlias == propertyTypeAlias &&
  427. ((Member)x).IntegerropertyValue > value);
  428. break;
  429. case ValuePropertyMatchType.LessThan:
  430. query =
  431. Query<IMember>.Builder.Where(
  432. x =>
  433. ((Member)x).PropertyTypeAlias == propertyTypeAlias &&
  434. ((Member)x).IntegerropertyValue < value);
  435. break;
  436. case ValuePropertyMatchType.GreaterThanOrEqualTo:
  437. query =
  438. Query<IMember>.Builder.Where(
  439. x =>
  440. ((Member)x).PropertyTypeAlias == propertyTypeAlias &&
  441. ((Member)x).IntegerropertyValue >= value);
  442. break;
  443. case ValuePropertyMatchType.LessThanOrEqualTo:
  444. query =
  445. Query<IMember>.Builder.Where(
  446. x =>
  447. ((Member)x).PropertyTypeAlias == propertyTypeAlias &&
  448. ((Member)x).IntegerropertyValue <= value);
  449. break;
  450. default:
  451. throw new ArgumentOutOfRangeException("matchType");
  452. }
  453. var members = repository.GetByQuery(query);
  454. return members;
  455. }
  456. }
  457. /// <summary>
  458. /// Gets a list of Members with a certain boolean property value
  459. /// </summary>
  460. /// <param name="propertyTypeAlias"></param>
  461. /// <param name="value"></param>
  462. /// <returns></returns>
  463. public IEnumerable<IMember> GetMembersByPropertyValue(string propertyTypeAlias, bool value)
  464. {
  465. using (var repository = _repositoryFactory.CreateMemberRepository(_uowProvider.GetUnitOfWork()))
  466. {
  467. var query =
  468. Query<IMember>.Builder.Where(
  469. x =>
  470. ((Member)x).PropertyTypeAlias == propertyTypeAlias &&
  471. ((Member)x).BoolPropertyValue == value);
  472. var members = repository.GetByQuery(query);
  473. return members;
  474. }
  475. }
  476. /// <summary>
  477. /// Gets a list of Members with a certain date time property value
  478. /// </summary>
  479. /// <param name="propertyTypeAlias"></param>
  480. /// <param name="value"></param>
  481. /// <param name="matchType"></param>
  482. /// <returns></returns>
  483. public IEnumerable<IMember> GetMembersByPropertyValue(string propertyTypeAlias, DateTime value, ValuePropertyMatchType matchType = ValuePropertyMatchType.Exact)
  484. {
  485. using (var repository = _repositoryFactory.CreateMemberRepository(_uowProvider.GetUnitOfWork()))
  486. {
  487. IQuery<IMember> query;
  488. switch (matchType)
  489. {
  490. case ValuePropertyMatchType.Exact:
  491. query =
  492. Query<IMember>.Builder.Where(
  493. x =>
  494. ((Member)x).PropertyTypeAlias == propertyTypeAlias &&
  495. ((Member)x).DateTimePropertyValue == value);
  496. break;
  497. case ValuePropertyMatchType.GreaterThan:
  498. query =
  499. Query<IMember>.Builder.Where(
  500. x =>
  501. ((Member)x).PropertyTypeAlias == propertyTypeAlias &&
  502. ((Member)x).DateTimePropertyValue > value);
  503. break;
  504. case ValuePropertyMatchType.LessThan:
  505. query =
  506. Query<IMember>.Builder.Where(
  507. x =>
  508. ((Member)x).PropertyTypeAlias == propertyTypeAlias &&
  509. ((Member)x).DateTimePropertyValue < value);
  510. break;
  511. case ValuePropertyMatchType.GreaterThanOrEqualTo:
  512. query =
  513. Query<IMember>.Builder.Where(
  514. x =>
  515. ((Member)x).PropertyTypeAlias == propertyTypeAlias &&
  516. ((Member)x).DateTimePropertyValue >= value);
  517. break;
  518. case ValuePropertyMatchType.LessThanOrEqualTo:
  519. query =
  520. Query<IMember>.Builder.Where(
  521. x =>
  522. ((Member)x).PropertyTypeAlias == propertyTypeAlias &&
  523. ((Member)x).DateTimePropertyValue <= value);
  524. break;
  525. default:
  526. throw new ArgumentOutOfRangeException("matchType");
  527. }
  528. var members = repository.GetByQuery(query);
  529. return members;
  530. }
  531. }
  532. #endregion
  533. #region IMembershipMemberService Implementation
  534. /// <summary>
  535. /// Returns the count of members based on the countType
  536. /// </summary>
  537. /// <param name="countType"></param>
  538. /// <returns></returns>
  539. /// <remarks>
  540. /// The way the Online count is done is the same way that it is done in the MS SqlMembershipProvider - We query for any members
  541. /// that have their last active date within the Membership.UserIsOnlineTimeWindow (which is in minutes). It isn't exact science
  542. /// but that is how MS have made theirs so we'll follow that principal.
  543. /// </remarks>
  544. public int GetCount(MemberCountType countType)
  545. {
  546. using (var repository = _repositoryFactory.CreateMemberRepository(_uowProvider.GetUnitOfWork()))
  547. {
  548. IQuery<IMember> query;
  549. switch (countType)
  550. {
  551. case MemberCountType.All:
  552. query = new Query<IMember>();
  553. return repository.Count(query);
  554. case MemberCountType.Online:
  555. var fromDate = DateTime.Now.AddMinutes(-Membership.UserIsOnlineTimeWindow);
  556. query =
  557. Query<IMember>.Builder.Where(
  558. x =>
  559. ((Member)x).PropertyTypeAlias == Constants.Conventions.Member.LastLoginDate &&
  560. ((Member)x).DateTimePropertyValue > fromDate);
  561. return repository.GetCountByQuery(query);
  562. case MemberCountType.LockedOut:
  563. query =
  564. Query<IMember>.Builder.Where(
  565. x =>
  566. ((Member)x).PropertyTypeAlias == Constants.Conventions.Member.IsLockedOut &&
  567. ((Member)x).BoolPropertyValue == true);
  568. return repository.GetCountByQuery(query);
  569. case MemberCountType.Approved:
  570. query =
  571. Query<IMember>.Builder.Where(
  572. x =>
  573. ((Member)x).PropertyTypeAlias == Constants.Conventions.Member.IsApproved &&
  574. ((Member)x).BoolPropertyValue == true);
  575. return repository.GetCountByQuery(query);
  576. default:
  577. throw new ArgumentOutOfRangeException("countType");
  578. }
  579. }
  580. }
  581. public IEnumerable<IMember> GetAll(int pageIndex, int pageSize, out int totalRecords)
  582. {
  583. var uow = _uowProvider.GetUnitOfWork();
  584. using (var repository = _repositoryFactory.CreateMemberRepository(uow))
  585. {
  586. return repository.GetPagedResultsByQuery(null, pageIndex, pageSize, out totalRecords, member => member.Username);
  587. }
  588. }
  589. /// <summary>
  590. /// Creates a member object
  591. /// </summary>
  592. /// <param name="username"></param>
  593. /// <param name="email"></param>
  594. /// <param name="name"></param>
  595. /// <param name="memberTypeAlias"></param>
  596. /// <returns></returns>
  597. public IMember CreateMember(string username, string email, string name, string memberTypeAlias)
  598. {
  599. var memberType = FindMemberTypeByAlias(memberTypeAlias);
  600. return CreateMember(username, email, name, memberType);
  601. }
  602. /// <summary>
  603. /// Creates a new member object
  604. /// </summary>
  605. /// <param name="username"></param>
  606. /// <param name="email"></param>
  607. /// <param name="name"></param>
  608. /// <param name="memberType"></param>
  609. /// <returns></returns>
  610. public IMember CreateMember(string username, string email, string name, IMemberType memberType)
  611. {
  612. var member = new Member(name, email.ToLower().Trim(), username, memberType);
  613. Created.RaiseEvent(new NewEventArgs<IMember>(member, false, memberType.Alias, -1), this);
  614. return member;
  615. }
  616. /// <summary>
  617. /// Creates a member with an Id
  618. /// </summary>
  619. /// <param name="username"></param>
  620. /// <param name="email"></param>
  621. /// <param name="name"></param>
  622. /// <param name="memberTypeAlias"></param>
  623. /// <returns></returns>
  624. public IMember CreateMemberWithIdentity(string username, string email, string name, string memberTypeAlias)
  625. {
  626. var memberType = FindMemberTypeByAlias(memberTypeAlias);
  627. return CreateMemberWithIdentity(username, email, name, memberType);
  628. }
  629. /// <summary>
  630. /// Creates a member with an Id, the username will be used as their name
  631. /// </summary>
  632. /// <param name="username"></param>
  633. /// <param name="email"></param>
  634. /// <param name="memberType"></param>
  635. /// <returns></returns>
  636. public IMember CreateMemberWithIdentity(string username, string email, IMemberType memberType)
  637. {
  638. return CreateMemberWithIdentity(username, email, username, memberType);
  639. }
  640. /// <summary>
  641. /// Creates a member with an Id
  642. /// </summary>
  643. /// <param name="username"></param>
  644. /// <param name="email"></param>
  645. /// <param name="name"></param>
  646. /// <param name="memberType"></param>
  647. /// <returns></returns>
  648. public IMember CreateMemberWithIdentity(string username, string email, string name, IMemberType memberType)
  649. {
  650. return CreateMemberWithIdentity(username, email, name, "", memberType);
  651. }
  652. /// <summary>
  653. /// Creates and persists a new Member
  654. /// </summary>
  655. /// <param name="email"></param>
  656. /// <param name="username"></param>
  657. /// <param name="rawPasswordValue"></param>
  658. /// <param name="memberTypeAlias"></param>
  659. /// <returns></returns>
  660. IMember IMembershipMemberService<IMember>.CreateWithIdentity(string username, string email, string rawPasswordValue, string memberTypeAlias)
  661. {
  662. var memberType = FindMemberTypeByAlias(memberTypeAlias);
  663. return CreateMemberWithIdentity(username, email, username, rawPasswordValue, memberType);
  664. }
  665. private IMember CreateMemberWithIdentity(string username, string email, string name, string rawPasswordValue, IMemberType memberType)
  666. {
  667. if (memberType == null) throw new ArgumentNullException("memberType");
  668. var member = new Member(name, email.ToLower().Trim(), username, rawPasswordValue, memberType);
  669. if (Saving.IsRaisedEventCancelled(new SaveEventArgs<IMember>(member), this))
  670. {
  671. member.WasCancelled = true;
  672. return member;
  673. }
  674. var uow = _uowProvider.GetUnitOfWork();
  675. using (var repository = _repositoryFactory.CreateMemberRepository(uow))
  676. {
  677. repository.AddOrUpdate(member);
  678. //insert the xml
  679. repository.AddOrUpdateContentXml(member, m => _entitySerializer.Serialize(_dataTypeService, m));
  680. // generate preview for blame history?
  681. if (UmbracoConfig.For.UmbracoSettings().Content.GlobalPreviewStorageEnabled)
  682. {
  683. repository.AddOrUpdatePreviewXml(member, m => _entitySerializer.Serialize(_dataTypeService, m));
  684. }
  685. uow.Commit();
  686. }
  687. Saved.RaiseEvent(new SaveEventArgs<IMember>(member, false), this);
  688. Created.RaiseEvent(new NewEventArgs<IMember>(member, false, memberType.Alias, -1), this);
  689. return member;
  690. }
  691. /// <summary>
  692. /// Gets a Member by its Id
  693. /// </summary>
  694. /// <remarks>
  695. /// The Id should be an integer or Guid.
  696. /// </remarks>
  697. /// <param name="id"></param>
  698. /// <returns></returns>
  699. public IMember GetByProviderKey(object id)
  700. {
  701. var asGuid = id.TryConvertTo<Guid>();
  702. if (asGuid.Success)
  703. {
  704. return GetByKey((Guid)id);
  705. }
  706. var asInt = id.TryConvertTo<int>();
  707. if (asInt.Success)
  708. {
  709. return GetById((int)id);
  710. }
  711. return null;
  712. }
  713. /// <summary>
  714. /// Gets a Member by its Email
  715. /// </summary>
  716. /// <param name="email"></param>
  717. /// <returns></returns>
  718. public IMember GetByEmail(string email)
  719. {
  720. var uow = _uowProvider.GetUnitOfWork();
  721. using (var repository = _repositoryFactory.CreateMemberRepository(uow))
  722. {
  723. var query = Query<IMember>.Builder.Where(x => x.Email.Equals(email));
  724. var member = repository.GetByQuery(query).FirstOrDefault();
  725. return member;
  726. }
  727. }
  728. /// <summary>
  729. /// Gets a Member by its Username
  730. /// </summary>
  731. /// <param name="userName"></param>
  732. /// <returns></returns>
  733. public IMember GetByUsername(string userName)
  734. {
  735. var uow = _uowProvider.GetUnitOfWork();
  736. using (var repository = _repositoryFactory.CreateMemberRepository(uow))
  737. {
  738. var query = Query<IMember>.Builder.Where(x => x.Username.Equals(userName));
  739. var member = repository.GetByQuery(query).FirstOrDefault();
  740. return member;
  741. }
  742. }
  743. /// <summary>
  744. /// Deletes a Member
  745. /// </summary>
  746. /// <param name="member"></param>
  747. public void Delete(IMember member)
  748. {
  749. if (Deleting.IsRaisedEventCancelled(new DeleteEventArgs<IMember>(member), this))
  750. return;
  751. var uow = _uowProvider.GetUnitOfWork();
  752. using (var repository = _repositoryFactory.CreateMemberRepository(uow))
  753. {
  754. repository.Delete(member);
  755. uow.Commit();
  756. }
  757. Deleted.RaiseEvent(new DeleteEventArgs<IMember>(member, false), this);
  758. }
  759. /// <summary>
  760. /// Saves an updated Member
  761. /// </summary>
  762. /// <param name="entity"></param>
  763. /// <param name="raiseEvents"></param>
  764. public void Save(IMember entity, bool raiseEvents = true)
  765. {
  766. if (raiseEvents)
  767. {
  768. if (Saving.IsRaisedEventCancelled(new SaveEventArgs<IMember>(entity), this))
  769. {
  770. return;
  771. }
  772. }
  773. var uow = _uowProvider.GetUnitOfWork();
  774. using (var repository = _repositoryFactory.CreateMemberRepository(uow))
  775. {
  776. repository.AddOrUpdate(entity);
  777. repository.AddOrUpdateContentXml(entity, m => _entitySerializer.Serialize(_dataTypeService, m));
  778. // generate preview for blame history?
  779. if (UmbracoConfig.For.UmbracoSettings().Content.GlobalPreviewStorageEnabled)
  780. {
  781. repository.AddOrUpdatePreviewXml(entity, m => _entitySerializer.Serialize(_dataTypeService, m));
  782. }
  783. uow.Commit();
  784. }
  785. if (raiseEvents)
  786. Saved.RaiseEvent(new SaveEventArgs<IMember>(entity, false), this);
  787. }
  788. public void Save(IEnumerable<IMember> entities, bool raiseEvents = true)
  789. {
  790. var asArray = entities.ToArray();
  791. if (raiseEvents)
  792. {
  793. if (Saving.IsRaisedEventCancelled(new SaveEventArgs<IMember>(asArray), this))
  794. return;
  795. }
  796. using (new WriteLock(Locker))
  797. {
  798. var uow = _uowProvider.GetUnitOfWork();
  799. using (var repository = _repositoryFactory.CreateMemberRepository(uow))
  800. {
  801. foreach (var member in asArray)
  802. {
  803. repository.AddOrUpdate(member);
  804. repository.AddOrUpdateContentXml(member, m => _entitySerializer.Serialize(_dataTypeService, m));
  805. // generate preview for blame history?
  806. if (UmbracoConfig.For.UmbracoSettings().Content.GlobalPreviewStorageEnabled)
  807. {
  808. repository.AddOrUpdatePreviewXml(member, m => _entitySerializer.Serialize(_dataTypeService, m));
  809. }
  810. }
  811. //commit the whole lot in one go
  812. uow.Commit();
  813. }
  814. if (raiseEvents)
  815. Saved.RaiseEvent(new SaveEventArgs<IMember>(asArray, false), this);
  816. }
  817. }
  818. #endregion
  819. #region IMembershipRoleService Implementation
  820. public void AddRole(string roleName)
  821. {
  822. var uow = _uowProvider.GetUnitOfWork();
  823. using (var repository = _repositoryFactory.CreateMemberGroupRepository(uow))
  824. {
  825. repository.CreateIfNotExists(roleName);
  826. }
  827. }
  828. public IEnumerable<string> GetAllRoles()
  829. {
  830. var uow = _uowProvider.GetUnitOfWork();
  831. using (var repository = _repositoryFactory.CreateMemberGroupRepository(uow))
  832. {
  833. var result = repository.GetAll();
  834. return result.Select(x => x.Name).Distinct();
  835. }
  836. }
  837. public IEnumerable<string> GetAllRoles(int memberId)
  838. {
  839. var uow = _uowProvider.GetUnitOfWork();
  840. using (var repository = _repositoryFactory.CreateMemberGroupRepository(uow))
  841. {
  842. var result = repository.GetMemberGroupsForMember(memberId);
  843. return result.Select(x => x.Name).Distinct();
  844. }
  845. }
  846. public IEnumerable<string> GetAllRoles(string username)
  847. {
  848. var uow = _uowProvider.GetUnitOfWork();
  849. using (var repository = _repositoryFactory.CreateMemberGroupRepository(uow))
  850. {
  851. var result = repository.GetMemberGroupsForMember(username);
  852. return result.Select(x => x.Name).Distinct();
  853. }
  854. }
  855. public IEnumerable<IMember> GetMembersInRole(string roleName)
  856. {
  857. var uow = _uowProvider.GetUnitOfWork();
  858. using (var repository = _repositoryFactory.CreateMemberRepository(uow))
  859. {
  860. return repository.GetByMemberGroup(roleName);
  861. }
  862. }
  863. public IEnumerable<IMember> FindMembersInRole(string roleName, string usernameToMatch, StringPropertyMatchType matchType = StringPropertyMatchType.StartsWith)
  864. {
  865. var uow = _uowProvider.GetUnitOfWork();
  866. using (var repository = _repositoryFactory.CreateMemberRepository(uow))
  867. {
  868. return repository.FindMembersInRole(roleName, usernameToMatch, matchType);
  869. }
  870. }
  871. public bool DeleteRole(string roleName, bool throwIfBeingUsed)
  872. {
  873. using (new WriteLock(Locker))
  874. {
  875. if (throwIfBeingUsed)
  876. {
  877. var inRole = GetMembersInRole(roleName);
  878. if (inRole.Any())
  879. {
  880. throw new InvalidOperationException("The role " + roleName + " is currently assigned to members");
  881. }
  882. }
  883. var uow = _uowProvider.GetUnitOfWork();
  884. using (var repository = _repositoryFactory.CreateMemberGroupRepository(uow))
  885. {
  886. var qry = new Query<IMemberGroup>().Where(g => g.Name == roleName);
  887. var found = repository.GetByQuery(qry).ToArray();
  888. foreach (var memberGroup in found)
  889. {
  890. _memberGroupService.Delete(memberGroup);
  891. }
  892. return found.Any();
  893. }
  894. }
  895. }
  896. public void AssignRole(string username, string roleName)
  897. {
  898. AssignRoles(new[] { username }, new[] { roleName });
  899. }
  900. public void AssignRoles(string[] usernames, string[] roleNames)
  901. {
  902. var uow = _uowProvider.GetUnitOfWork();
  903. using (var repository = _repositoryFactory.CreateMemberGroupRepository(uow))
  904. {
  905. repository.AssignRoles(usernames, roleNames);
  906. }
  907. }
  908. public void DissociateRole(string username, string roleName)
  909. {
  910. DissociateRoles(new[] { username }, new[] { roleName });
  911. }
  912. public void DissociateRoles(string[] usernames, string[] roleNames)
  913. {
  914. var uow = _uowProvider.GetUnitOfWork();
  915. using (var repository = _repositoryFactory.CreateMemberGroupRepository(uow))
  916. {
  917. repository.DissociateRoles(usernames, roleNames);
  918. }
  919. }
  920. public void AssignRole(int memberId, string roleName)
  921. {
  922. AssignRoles(new[] { memberId }, new[] { roleName });
  923. }
  924. public void AssignRoles(int[] memberIds, string[] roleNames)
  925. {
  926. var uow = _uowProvider.GetUnitOfWork();
  927. using (var repository = _repositoryFactory.CreateMemberGroupRepository(uow))
  928. {
  929. repository.AssignRoles(memberIds, roleNames);
  930. }
  931. }
  932. public void DissociateRole(int memberId, string roleName)
  933. {
  934. DissociateRoles(new[] { memberId }, new[] { roleName });
  935. }
  936. public void DissociateRoles(int[] memberIds, string[] roleNames)
  937. {
  938. var uow = _uowProvider.GetUnitOfWork();
  939. using (var repository = _repositoryFactory.CreateMemberGroupRepository(uow))
  940. {
  941. repository.DissociateRoles(memberIds, roleNames);
  942. }
  943. }
  944. #endregion
  945. private IMemberType FindMemberTypeByAlias(string memberTypeAlias)
  946. {
  947. using (var repository = _repositoryFactory.CreateMemberTypeRepository(_uowProvider.GetUnitOfWork()))
  948. {
  949. var query = Query<IMemberType>.Builder.Where(x => x.Alias == memberTypeAlias);
  950. var types = repository.GetByQuery(query);
  951. if (types.Any() == false)
  952. throw new Exception(
  953. string.Format("No MemberType matching the passed in Alias: '{0}' was found",
  954. memberTypeAlias));
  955. var contentType = types.First();
  956. if (contentType == null)
  957. throw new Exception(string.Format("MemberType matching the passed in Alias: '{0}' was null",
  958. memberTypeAlias));
  959. return contentType;
  960. }
  961. }
  962. /// <summary>
  963. /// Rebuilds all xml content in the cmsContentXml table for all members
  964. /// </summary>
  965. /// <param name="memberTypeIds">
  966. /// Only rebuild the xml structures for the content type ids passed in, if none then rebuilds the structures
  967. /// for all members = USE WITH CARE!
  968. /// </param>
  969. /// <returns>True if publishing succeeded, otherwise False</returns>
  970. internal void RebuildXmlStructures(params int[] memberTypeIds)
  971. {
  972. using (new WriteLock(Locker))
  973. {
  974. var list = new List<IMember>();
  975. var uow = _uowProvider.GetUnitOfWork();
  976. //First we're going to get the data that needs to be inserted before clearing anything, this
  977. //ensures that we don't accidentally leave the content xml table empty if something happens
  978. //during the lookup process.
  979. if (memberTypeIds.Any() == false)
  980. {
  981. list.AddRange(GetAllMembers());
  982. }
  983. else
  984. {
  985. list.AddRange(memberTypeIds.SelectMany(GetMembersByMemberType));
  986. }
  987. var xmlItems = new List<ContentXmlDto>();
  988. foreach (var c in list)
  989. {
  990. var xml = _entitySerializer.Serialize(_dataTypeService, c);
  991. xmlItems.Add(new ContentXmlDto { NodeId = c.Id, Xml = xml.ToString(SaveOptions.None) });
  992. }
  993. //Ok, now we need to remove the data and re-insert it, we'll do this all in one transaction too.
  994. using (var tr = uow.Database.GetTransaction())
  995. {
  996. if (memberTypeIds.Any() == false)
  997. {
  998. //Remove all member records from the cmsContentXml table (DO NOT REMOVE Content/Media!)
  999. var memberObjectType = Guid.Parse(Constants.ObjectTypes.Member);
  1000. var subQuery = new Sql()
  1001. .Select("DISTINCT cmsContentXml.nodeId")
  1002. .From<ContentXmlDto>()
  1003. .InnerJoin<NodeDto>()
  1004. .On<ContentXmlDto, NodeDto>(left => left.NodeId, right => right.NodeId)
  1005. .Where<NodeDto>(dto => dto.NodeObjectType == memberObjectType);
  1006. var deleteSql = SqlSyntaxContext.SqlSyntaxProvider.GetDeleteSubquery("cmsContentXml", "nodeId", subQuery);
  1007. uow.Database.Execute(deleteSql);
  1008. }
  1009. else
  1010. {
  1011. foreach (var id in memberTypeIds)
  1012. {
  1013. var id1 = id;
  1014. var memberObjectType = Guid.Parse(Constants.ObjectTypes.Member);
  1015. var subQuery = new Sql()
  1016. .Select("DISTINCT cmsContentXml.nodeId")
  1017. .From<ContentXmlDto>()
  1018. .InnerJoin<NodeDto>()
  1019. .On<ContentXmlDto, NodeDto>(left => left.NodeId, right => right.NodeId)
  1020. .InnerJoin<ContentDto>()
  1021. .On<ContentDto, NodeDto>(left => left.

Large files files are truncated, but you can click here to view the full file