Fixed: Don't allow profile delete if in use by import list

Fixes #280
pull/284/head
Qstick 6 years ago
parent e5c5a3f91c
commit fde276f000

@ -8,7 +8,7 @@ import createDimensionsSelector from 'Store/Selectors/createDimensionsSelector';
import { saveDimensions, setIsSidebarVisible } from 'Store/Actions/appActions';
import { fetchArtist } from 'Store/Actions/artistActions';
import { fetchTags } from 'Store/Actions/tagActions';
import { fetchQualityProfiles, fetchLanguageProfiles, fetchMetadataProfiles, fetchUISettings } from 'Store/Actions/settingsActions';
import { fetchQualityProfiles, fetchLanguageProfiles, fetchMetadataProfiles, fetchUISettings, fetchImportLists } from 'Store/Actions/settingsActions';
import { fetchStatus } from 'Store/Actions/systemActions';
import ErrorPage from './ErrorPage';
import LoadingPage from './LoadingPage';
@ -38,11 +38,17 @@ function createMapStateToProps() {
const isPopulated = artist.isPopulated &&
tags.isPopulated &&
settings.qualityProfiles.isPopulated &&
settings.languageProfiles.isPopulated &&
settings.metadataProfiles.isPopulated &&
settings.importLists.isPopulated &&
settings.ui.isPopulated;
const hasError = !!artist.error ||
!!tags.error ||
!!settings.qualityProfiles.error ||
!!settings.languageProfiles.error ||
!!settings.metadataProfiles.error ||
!!settings.importLists.error ||
!!settings.ui.error;
return {
@ -51,6 +57,9 @@ function createMapStateToProps() {
artistError: artist.error,
tagsError: tags.error,
qualityProfilesError: settings.qualityProfiles.error,
languageProfilesError: settings.languageProfiles.error,
metadataProfilesError: settings.metadataProfiles.error,
importListsError: settings.importLists.error,
uiSettingsError: settings.ui.error,
isSmallScreen: dimensions.isSmallScreen,
isSidebarVisible: app.isSidebarVisible,
@ -79,6 +88,9 @@ function createMapDispatchToProps(dispatch, props) {
dispatchFetchMetadataProfiles() {
dispatch(fetchMetadataProfiles());
},
dispatchFetchImportLists() {
dispatch(fetchImportLists());
},
dispatchFetchUISettings() {
dispatch(fetchUISettings());
},
@ -114,6 +126,7 @@ class PageConnector extends Component {
this.props.dispatchFetchQualityProfiles();
this.props.dispatchFetchLanguageProfiles();
this.props.dispatchFetchMetadataProfiles();
this.props.dispatchFetchImportLists();
this.props.dispatchFetchUISettings();
this.props.dispatchFetchStatus();
}
@ -138,6 +151,7 @@ class PageConnector extends Component {
dispatchFetchQualityProfiles,
dispatchFetchLanguageProfiles,
dispatchFetchMetadataProfiles,
dispatchFetchImportLists,
dispatchFetchUISettings,
dispatchFetchStatus,
...otherProps
@ -176,6 +190,7 @@ PageConnector.propTypes = {
dispatchFetchQualityProfiles: PropTypes.func.isRequired,
dispatchFetchLanguageProfiles: PropTypes.func.isRequired,
dispatchFetchMetadataProfiles: PropTypes.func.isRequired,
dispatchFetchImportLists: PropTypes.func.isRequired,
dispatchFetchUISettings: PropTypes.func.isRequired,
dispatchFetchStatus: PropTypes.func.isRequired,
onSidebarVisibleChange: PropTypes.func.isRequired

@ -41,7 +41,7 @@ function EditImportListModalContent(props) {
enableAutomaticAdd,
shouldMonitor,
rootFolderPath,
profileId,
qualityProfileId,
languageProfileId,
metadataProfileId,
fields
@ -121,9 +121,9 @@ function EditImportListModalContent(props) {
<FormInputGroup
type={inputTypes.QUALITY_PROFILE_SELECT}
name="profileId"
name="qualityProfileId"
helpText={'Quality Profile list items should be added with'}
{...profileId}
{...qualityProfileId}
onChange={onInputChange}
/>
</FormGroup>

@ -101,7 +101,7 @@ function EditLanguageProfileModalContent(props) {
id &&
<div
className={styles.deleteButtonContainer}
title={isInUse ? 'Can\'t delete a language profile that is attached to a artist' : undefined}
title={isInUse ? 'Can\'t delete a language profile that is attached to an artist or import list' : undefined}
>
<Button
kind={kinds.DANGER}

@ -107,7 +107,7 @@ function EditMetadataProfileModalContent(props) {
id &&
<div
className={styles.deleteButtonContainer}
title={isInUse ? 'Can\'t delete a metadata profile that is attached to a artist' : undefined}
title={isInUse ? 'Can\'t delete a metadata profile that is attached to an artist or import list' : undefined}
>
<Button
kind={kinds.DANGER}

@ -200,7 +200,7 @@ class EditQualityProfileModalContent extends Component {
id &&
<div
className={styles.deleteButtonContainer}
title={isInUse ? 'Can\'t delete a quality profile that is attached to a artist' : undefined}
title={isInUse ? 'Can\'t delete a quality profile that is attached to an artist or import list' : undefined}
>
<Button
kind={kinds.DANGER}

@ -6,12 +6,17 @@ function createProfileInUseSelector(profileProp) {
return createSelector(
(state, { id }) => id,
createAllArtistSelector(),
(id, artist) => {
(state) => state.settings.importLists.items,
(id, artist, lists) => {
if (!id) {
return false;
}
return _.some(artist, { [profileProp]: id });
if (_.some(artist, { [profileProp]: id }) || _.some(lists, { [profileProp]: id })) {
return true;
}
return false;
}
);
}

@ -7,7 +7,7 @@ namespace Lidarr.Api.V1.ImportLists
public bool EnableAutomaticAdd { get; set; }
public bool ShouldMonitor { get; set; }
public string RootFolderPath { get; set; }
public int ProfileId { get; set; }
public int QualityProfileId { get; set; }
public int LanguageProfileId { get; set; }
public int MetadataProfileId { get; set; }
}
@ -26,7 +26,7 @@ namespace Lidarr.Api.V1.ImportLists
resource.EnableAutomaticAdd = definition.EnableAutomaticAdd;
resource.ShouldMonitor = definition.ShouldMonitor;
resource.RootFolderPath = definition.RootFolderPath;
resource.ProfileId = definition.ProfileId;
resource.QualityProfileId = definition.ProfileId;
resource.LanguageProfileId = definition.LanguageProfileId;
resource.MetadataProfileId = definition.MetadataProfileId;
@ -45,7 +45,7 @@ namespace Lidarr.Api.V1.ImportLists
definition.EnableAutomaticAdd = resource.EnableAutomaticAdd;
definition.ShouldMonitor = resource.ShouldMonitor;
definition.RootFolderPath = resource.RootFolderPath;
definition.ProfileId = resource.ProfileId;
definition.ProfileId = resource.QualityProfileId;
definition.LanguageProfileId = resource.LanguageProfileId;
definition.MetadataProfileId = resource.MetadataProfileId;

@ -1,6 +1,7 @@
using System.Collections.Generic;
using System.Linq;
using NLog;
using NzbDrone.Core.ImportLists;
using NzbDrone.Core.Lifecycle;
using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Languages;
@ -22,12 +23,14 @@ namespace NzbDrone.Core.Profiles.Languages
{
private readonly ILanguageProfileRepository _profileRepository;
private readonly IArtistService _artistService;
private readonly IImportListFactory _importListFactory;
private readonly Logger _logger;
public LanguageProfileService(ILanguageProfileRepository profileRepository, IArtistService artistService, Logger logger)
public LanguageProfileService(ILanguageProfileRepository profileRepository, IArtistService artistService, IImportListFactory importListFactory, Logger logger)
{
_profileRepository = profileRepository;
_artistService = artistService;
_importListFactory = importListFactory;
_logger = logger;
}
@ -43,7 +46,7 @@ namespace NzbDrone.Core.Profiles.Languages
public void Delete(int id)
{
if (_artistService.GetAllArtists().Any(c => c.LanguageProfileId == id))
if (_artistService.GetAllArtists().Any(c => c.LanguageProfileId == id) || _importListFactory.All().Any(c => c.LanguageProfileId == id))
{
var profile = _profileRepository.Get(id);
throw new LanguageProfileInUseException(profile.Name);

@ -4,6 +4,7 @@ using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Music;
using System.Collections.Generic;
using System.Linq;
using NzbDrone.Core.ImportLists;
namespace NzbDrone.Core.Profiles.Metadata
{
@ -21,12 +22,17 @@ namespace NzbDrone.Core.Profiles.Metadata
{
private readonly IMetadataProfileRepository _profileRepository;
private readonly IArtistService _artistService;
private readonly IImportListFactory _importListFactory;
private readonly Logger _logger;
public MetadataProfileService(IMetadataProfileRepository profileRepository, IArtistService artistService, Logger logger)
public MetadataProfileService(IMetadataProfileRepository profileRepository,
IArtistService artistService,
IImportListFactory importListFactory,
Logger logger)
{
_profileRepository = profileRepository;
_artistService = artistService;
_importListFactory = importListFactory;
_logger = logger;
}
@ -42,7 +48,7 @@ namespace NzbDrone.Core.Profiles.Metadata
public void Delete(int id)
{
if (_artistService.GetAllArtists().Any(c => c.MetadataProfileId == id))
if (_artistService.GetAllArtists().Any(c => c.MetadataProfileId == id) || _importListFactory.All().Any(c => c.MetadataProfileId == id))
{
var profile = _profileRepository.Get(id);
throw new MetadataProfileInUseException(profile.Name);

@ -3,6 +3,7 @@ using System.Linq;
using NLog;
using NzbDrone.Common.Extensions;
using NzbDrone.Common.Http.Dispatchers;
using NzbDrone.Core.ImportLists;
using NzbDrone.Core.Lifecycle;
using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Qualities;
@ -26,12 +27,14 @@ namespace NzbDrone.Core.Profiles.Qualities
{
private readonly IProfileRepository _profileRepository;
private readonly IArtistService _artistService;
private readonly IImportListFactory _importListFactory;
private readonly Logger _logger;
public ProfileService(IProfileRepository profileRepository, IArtistService artistService, Logger logger)
public ProfileService(IProfileRepository profileRepository, IArtistService artistService, IImportListFactory importListFactory, Logger logger)
{
_profileRepository = profileRepository;
_artistService = artistService;
_importListFactory = importListFactory;
_logger = logger;
}
@ -47,7 +50,7 @@ namespace NzbDrone.Core.Profiles.Qualities
public void Delete(int id)
{
if (_artistService.GetAllArtists().Any(c => c.ProfileId == id))
if (_artistService.GetAllArtists().Any(c => c.ProfileId == id) || _importListFactory.All().Any(c => c.ProfileId == id))
{
var profile = _profileRepository.Get(id);
throw new ProfileInUseException(profile.Name);

Loading…
Cancel
Save