V14: Member group controller (#15669)
* Add models & mapping * Add controller * Add create async to service * Add auth policy * Implement delete * Rename response model * Implement updateAsync * Refactor update to use own model * Implement all async counterparts for IMemberService * Add tests * Implement update member group mapping * Dont fail if updating the current user group * Return not found if not found * Add missing OperationResults to MemberGroupOperationStatusResult * Add 404 to response type * Update openapi * Update OpenApi * Update OpenApi.json
This commit is contained in:
@@ -1,20 +1,74 @@
|
||||
using Umbraco.Cms.Core.Models;
|
||||
using Umbraco.Cms.Core.Services.OperationStatus;
|
||||
|
||||
namespace Umbraco.Cms.Core.Services;
|
||||
|
||||
public interface IMemberGroupService : IService
|
||||
{
|
||||
[Obsolete("Please use the asynchronous counterpart. Scheduled for removal in v15.")]
|
||||
IEnumerable<IMemberGroup> GetAll();
|
||||
|
||||
[Obsolete("Please use Guid instead of Int id. Scheduled for removal in v15.")]
|
||||
IMemberGroup? GetById(int id);
|
||||
|
||||
[Obsolete("Please use the asynchronous counterpart. Scheduled for removal in v15.")]
|
||||
IMemberGroup? GetById(Guid id);
|
||||
|
||||
[Obsolete("Please use the asynchronous counterpart. Scheduled for removal in v15.")]
|
||||
IEnumerable<IMemberGroup> GetByIds(IEnumerable<int> ids);
|
||||
|
||||
IMemberGroup? GetByName(string? name);
|
||||
|
||||
[Obsolete("Please use the respective CreateAsync/UpdateAsync for you save operations. Scheduled for removal in v15.")]
|
||||
void Save(IMemberGroup memberGroup);
|
||||
|
||||
[Obsolete("Please use the asynchronous counterpart. Scheduled for removal in v15.")]
|
||||
void Delete(IMemberGroup memberGroup);
|
||||
|
||||
/// <summary>
|
||||
/// Get a member group by name.
|
||||
/// </summary>
|
||||
/// <param name="name">Name of the member group to get.</param>
|
||||
/// <returns>A <see cref="IMemberGroup" /> object.</returns>
|
||||
Task<IMemberGroup?> GetByNameAsync(string name);
|
||||
|
||||
/// <summary>
|
||||
/// Get a member group by key.
|
||||
/// </summary>
|
||||
/// <param name="key"><see cref="Guid" /> of the member group to get.</param>
|
||||
/// <returns>A <see cref="IMemberGroup" /> object.</returns>
|
||||
Task<IMemberGroup?> GetAsync(Guid key);
|
||||
|
||||
/// <summary>
|
||||
/// Gets all member groups
|
||||
/// </summary>
|
||||
/// <returns>An enumerable list of <see cref="IMemberGroup" /> objects.</returns>
|
||||
Task<IEnumerable<IMemberGroup>> GetAllAsync();
|
||||
|
||||
/// <summary>
|
||||
/// Gets a list of member groups with the given ids.
|
||||
/// </summary>
|
||||
/// <param name="ids">An enumerable list of <see cref="int" /> ids, to get the member groups by.</param>
|
||||
/// <returns>An enumerable list of <see cref="IMemberGroup" /> objects.</returns>
|
||||
Task<IEnumerable<IMemberGroup>> GetByIdsAsync(IEnumerable<int> ids);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="IMemberGroup" /> object
|
||||
/// </summary>
|
||||
/// <param name="memberGroup"><see cref="IMemberGroup" /> to create</param>
|
||||
/// <returns>An attempt with a status of whether the operation was successful or not, and the created object if it succeeded.</returns>
|
||||
Task<Attempt<IMemberGroup?, MemberGroupOperationStatus>> CreateAsync(IMemberGroup memberGroup);
|
||||
|
||||
/// <summary>
|
||||
/// Deletes a <see cref="IMemberGroup" /> by removing it and its usages from the db
|
||||
/// </summary>
|
||||
/// <param name="key">The key of the <see cref="IMemberGroup" /> to delete</param>
|
||||
Task<Attempt<IMemberGroup?, MemberGroupOperationStatus>> DeleteAsync(Guid key);
|
||||
|
||||
/// <summary>
|
||||
/// Updates <see cref="IMemberGroup" /> object
|
||||
/// </summary>
|
||||
/// <param name="memberGroup"><see cref="IMemberGroup" /> to create</param>
|
||||
/// <returns>An attempt with a status of whether the operation was successful or not, and the object.</returns>
|
||||
Task<Attempt<IMemberGroup?, MemberGroupOperationStatus>> UpdateAsync(IMemberGroup memberGroup);
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ using Umbraco.Cms.Core.Models;
|
||||
using Umbraco.Cms.Core.Notifications;
|
||||
using Umbraco.Cms.Core.Persistence.Repositories;
|
||||
using Umbraco.Cms.Core.Scoping;
|
||||
using Umbraco.Cms.Core.Services.OperationStatus;
|
||||
|
||||
namespace Umbraco.Cms.Core.Services;
|
||||
|
||||
@@ -15,26 +16,9 @@ internal class MemberGroupService : RepositoryService, IMemberGroupService
|
||||
: base(provider, loggerFactory, eventMessagesFactory) =>
|
||||
_memberGroupRepository = memberGroupRepository;
|
||||
|
||||
public IEnumerable<IMemberGroup> GetAll()
|
||||
{
|
||||
using (ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true))
|
||||
{
|
||||
return _memberGroupRepository.GetMany();
|
||||
}
|
||||
}
|
||||
public IEnumerable<IMemberGroup> GetAll() => GetAllAsync().GetAwaiter().GetResult();
|
||||
|
||||
public IEnumerable<IMemberGroup> GetByIds(IEnumerable<int> ids)
|
||||
{
|
||||
if (ids == null || ids.Any() == false)
|
||||
{
|
||||
return new IMemberGroup[0];
|
||||
}
|
||||
|
||||
using (ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true))
|
||||
{
|
||||
return _memberGroupRepository.GetMany(ids.ToArray());
|
||||
}
|
||||
}
|
||||
public IEnumerable<IMemberGroup> GetByIds(IEnumerable<int> ids) => GetByIdsAsync(ids).GetAwaiter().GetResult();
|
||||
|
||||
public IMemberGroup? GetById(int id)
|
||||
{
|
||||
@@ -44,21 +28,9 @@ internal class MemberGroupService : RepositoryService, IMemberGroupService
|
||||
}
|
||||
}
|
||||
|
||||
public IMemberGroup? GetById(Guid id)
|
||||
{
|
||||
using (ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true))
|
||||
{
|
||||
return _memberGroupRepository.Get(id);
|
||||
}
|
||||
}
|
||||
public IMemberGroup? GetById(Guid id) => GetAsync(id).GetAwaiter().GetResult();
|
||||
|
||||
public IMemberGroup? GetByName(string? name)
|
||||
{
|
||||
using (ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true))
|
||||
{
|
||||
return _memberGroupRepository.GetByName(name);
|
||||
}
|
||||
}
|
||||
public IMemberGroup? GetByName(string? name) => name is null ? null : GetByNameAsync(name).GetAwaiter().GetResult();
|
||||
|
||||
public void Save(IMemberGroup memberGroup)
|
||||
{
|
||||
@@ -86,24 +58,139 @@ internal class MemberGroupService : RepositoryService, IMemberGroupService
|
||||
}
|
||||
}
|
||||
|
||||
public void Delete(IMemberGroup memberGroup)
|
||||
public void Delete(IMemberGroup memberGroup) => DeleteAsync(memberGroup.Key).GetAwaiter().GetResult();
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Task<IMemberGroup?> GetByNameAsync(string name)
|
||||
{
|
||||
EventMessages evtMsgs = EventMessagesFactory.Get();
|
||||
using ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true);
|
||||
return Task.FromResult(_memberGroupRepository.GetByName(name));
|
||||
}
|
||||
|
||||
using (ICoreScope scope = ScopeProvider.CreateCoreScope())
|
||||
/// <inheritdoc/>
|
||||
public Task<IMemberGroup?> GetAsync(Guid key)
|
||||
{
|
||||
using ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true);
|
||||
return Task.FromResult(_memberGroupRepository.Get(key));
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Task<IEnumerable<IMemberGroup>> GetAllAsync()
|
||||
{
|
||||
using ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true);
|
||||
return Task.FromResult(_memberGroupRepository.GetMany());
|
||||
}
|
||||
|
||||
public Task<IEnumerable<IMemberGroup>> GetByIdsAsync(IEnumerable<int> ids)
|
||||
{
|
||||
if (ids.Any() == false)
|
||||
{
|
||||
var deletingNotification = new MemberGroupDeletingNotification(memberGroup, evtMsgs);
|
||||
if (scope.Notifications.PublishCancelable(deletingNotification))
|
||||
{
|
||||
scope.Complete();
|
||||
return;
|
||||
}
|
||||
|
||||
_memberGroupRepository.Delete(memberGroup);
|
||||
scope.Complete();
|
||||
|
||||
scope.Notifications.Publish(
|
||||
new MemberGroupDeletedNotification(memberGroup, evtMsgs).WithStateFrom(deletingNotification));
|
||||
return Task.FromResult<IEnumerable<IMemberGroup>>(Array.Empty<IMemberGroup>());
|
||||
}
|
||||
|
||||
using ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true);
|
||||
return Task.FromResult(_memberGroupRepository.GetMany(ids.ToArray()));
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public async Task<Attempt<IMemberGroup?, MemberGroupOperationStatus>> CreateAsync(IMemberGroup memberGroup)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(memberGroup.Name))
|
||||
{
|
||||
return Attempt.FailWithStatus<IMemberGroup?, MemberGroupOperationStatus>(MemberGroupOperationStatus.CannotHaveEmptyName, null);
|
||||
}
|
||||
|
||||
EventMessages eventMessages = EventMessagesFactory.Get();
|
||||
|
||||
using ICoreScope scope = ScopeProvider.CreateCoreScope();
|
||||
IMemberGroup? existingMemberGroup = await GetAsync(memberGroup.Key);
|
||||
if (existingMemberGroup is not null)
|
||||
{
|
||||
return Attempt.FailWithStatus<IMemberGroup?, MemberGroupOperationStatus>(MemberGroupOperationStatus.DuplicateKey, null);
|
||||
}
|
||||
|
||||
if (await NameAlreadyExistsAsync(memberGroup))
|
||||
{
|
||||
return Attempt.FailWithStatus<IMemberGroup?, MemberGroupOperationStatus>(MemberGroupOperationStatus.DuplicateName, null);
|
||||
}
|
||||
|
||||
var savingNotification = new MemberGroupSavingNotification(memberGroup, eventMessages);
|
||||
if (await scope.Notifications.PublishCancelableAsync(savingNotification))
|
||||
{
|
||||
scope.Complete();
|
||||
return Attempt.FailWithStatus<IMemberGroup?, MemberGroupOperationStatus>(MemberGroupOperationStatus.CancelledByNotification, null);
|
||||
}
|
||||
|
||||
_memberGroupRepository.Save(memberGroup);
|
||||
scope.Complete();
|
||||
|
||||
scope.Notifications.Publish(new MemberGroupSavedNotification(memberGroup, eventMessages).WithStateFrom(savingNotification));
|
||||
return Attempt.SucceedWithStatus<IMemberGroup?, MemberGroupOperationStatus>(MemberGroupOperationStatus.Success, memberGroup);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public async Task<Attempt<IMemberGroup?, MemberGroupOperationStatus>> DeleteAsync(Guid key)
|
||||
{
|
||||
EventMessages eventMessages = EventMessagesFactory.Get();
|
||||
|
||||
using ICoreScope scope = ScopeProvider.CreateCoreScope();
|
||||
IMemberGroup? memberGroup = _memberGroupRepository.Get(key);
|
||||
|
||||
if (memberGroup is null)
|
||||
{
|
||||
return Attempt.FailWithStatus<IMemberGroup?, MemberGroupOperationStatus>(MemberGroupOperationStatus.NotFound, null);
|
||||
}
|
||||
|
||||
var deletingNotification = new MemberGroupDeletingNotification(memberGroup, eventMessages);
|
||||
if (await scope.Notifications.PublishCancelableAsync(deletingNotification))
|
||||
{
|
||||
scope.Complete();
|
||||
return Attempt.FailWithStatus<IMemberGroup?, MemberGroupOperationStatus>(MemberGroupOperationStatus.CancelledByNotification, null);
|
||||
}
|
||||
|
||||
_memberGroupRepository.Delete(memberGroup);
|
||||
scope.Complete();
|
||||
|
||||
scope.Notifications.Publish(new MemberGroupDeletedNotification(memberGroup, eventMessages).WithStateFrom(deletingNotification));
|
||||
|
||||
return Attempt.SucceedWithStatus<IMemberGroup?, MemberGroupOperationStatus>(MemberGroupOperationStatus.Success, memberGroup);
|
||||
}
|
||||
|
||||
public async Task<Attempt<IMemberGroup?, MemberGroupOperationStatus>> UpdateAsync(IMemberGroup memberGroup)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(memberGroup.Name))
|
||||
{
|
||||
return Attempt.FailWithStatus<IMemberGroup?, MemberGroupOperationStatus>(MemberGroupOperationStatus.CannotHaveEmptyName, null);
|
||||
}
|
||||
|
||||
EventMessages eventMessages = EventMessagesFactory.Get();
|
||||
|
||||
using ICoreScope scope = ScopeProvider.CreateCoreScope();
|
||||
|
||||
IMemberGroup? existingMemberGroup = await GetByNameAsync(memberGroup.Name!);
|
||||
|
||||
if (existingMemberGroup is not null && existingMemberGroup.Key != memberGroup.Key)
|
||||
{
|
||||
return Attempt.FailWithStatus<IMemberGroup?, MemberGroupOperationStatus>(MemberGroupOperationStatus.DuplicateName, null);
|
||||
}
|
||||
|
||||
var savingNotification = new MemberGroupSavingNotification(memberGroup, eventMessages);
|
||||
if (await scope.Notifications.PublishCancelableAsync(savingNotification))
|
||||
{
|
||||
scope.Complete();
|
||||
return Attempt.FailWithStatus<IMemberGroup?, MemberGroupOperationStatus>(MemberGroupOperationStatus.CancelledByNotification, null);
|
||||
}
|
||||
|
||||
_memberGroupRepository.Save(memberGroup);
|
||||
scope.Complete();
|
||||
|
||||
scope.Notifications.Publish(new MemberGroupSavedNotification(memberGroup, eventMessages).WithStateFrom(savingNotification));
|
||||
return Attempt.SucceedWithStatus<IMemberGroup?, MemberGroupOperationStatus>(MemberGroupOperationStatus.Success, memberGroup);
|
||||
}
|
||||
|
||||
private async Task<bool> NameAlreadyExistsAsync(IMemberGroup memberGroup)
|
||||
{
|
||||
IMemberGroup? existingMemberGroup = await GetByNameAsync(memberGroup.Name!);
|
||||
return existingMemberGroup is not null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
namespace Umbraco.Cms.Core.Services.OperationStatus;
|
||||
|
||||
public enum MemberGroupOperationStatus
|
||||
{
|
||||
Success,
|
||||
NotFound,
|
||||
CannotHaveEmptyName,
|
||||
CancelledByNotification,
|
||||
DuplicateName,
|
||||
DuplicateKey,
|
||||
}
|
||||
Reference in New Issue
Block a user