コード例 #1
0
        /// <exception cref="ArgumentNullException">The specified arguments are null</exception>
        /// <exception cref="ArgumentException">A feature with the specified name already exists</exception>
        /// <exception cref="ResourceNotFoundException{Feature}">The referenced parent feature does not exist</exception>
        public Feature CreateFeature(FeatureArgs args)
        {
            if (args == null)
            {
                throw new ArgumentNullException(nameof(args));
            }

            if (Db.Features.Any(f => f.Name == args.Name))
            {
                throw new ArgumentException($"A feature with name '{args.Name}' already exists");
            }

            var feature = new Feature {
                Name = args.Name
            };

            if (args.Parent != null)
            {
                feature.Parent = GetFeature(args.Parent.Value);

                if (feature.Parent == null)
                {
                    throw new ResourceNotFoundException <Feature>(args.Parent);
                }
            }

            Db.Features.Add(feature);
            Db.SaveChanges();
            return(feature);
        }
コード例 #2
0
        public IActionResult Create([FromBody] FeatureArgs args)
        {
            if (!UserPermissions.IsAllowedToAdminister(User.Identity))
            {
                return(Forbid());
            }

            if (!ModelState.IsValid)
            {
                return(BadRequest(ModelState));
            }

            try
            {
                var feature = _manager.CreateFeature(args);
                return(Created($"{Request.Scheme}://{Request.Host}/api/Features/{feature.Id}", feature.Id));
            }
            catch (ResourceNotFoundException <Feature> e)
            {
                return(StatusCode(422, e.Message)); // invalid parent feature ID
            }
            catch (ArgumentException e)
            {
                return(StatusCode(409, e.Message)); // feature name already in use
            }
        }
コード例 #3
0
        public IActionResult Update(int featureId, [FromBody] FeatureArgs args)
        {
            if (!UserPermissions.IsAllowedToAdminister(User.Identity))
            {
                return(Forbid());
            }

            if (!ModelState.IsValid)
            {
                return(BadRequest(ModelState));
            }

            try
            {
                _manager.UpdateFeature(featureId, args);
                return(NoContent());
            }
            catch (ArgumentException e)
            {
                return(StatusCode(409, e.Message)); // new feature name already in use
            }
            catch (ResourceNotFoundException <Feature> e) when((int?)e.Keys.FirstOrDefault() == featureId)
            {
                return(NotFound(e.Message)); // feature to be updated does not exist
            }
            catch (ResourceNotFoundException <Feature> e)
            {
                return(StatusCode(422, e.Message)); // referenced parent feature does not exist
            }
            catch (InvalidOperationException e)
            {
                return(StatusCode(409, e.Message)); // invalid parent modification
            }
        }
コード例 #4
0
        /// <summary>
        /// Updates a feature. If the reference to the parent is modified, this moves the whole subtree of features.
        /// </summary>
        /// <exception cref="ArgumentNullException">The specified arguments are null</exception>
        /// <exception cref="ArgumentException">The new feature name is already in use</exception>
        /// <exception cref="ResourceNotFoundException{Feature}">There is no feature with the specified ID</exception>
        /// <exception cref="InvalidOperationException">Parent modification causes a cycle (destroys tree structure)</exception>
        public void UpdateFeature(int featureId, FeatureArgs args)
        {
            if (args == null)
            {
                throw new ArgumentNullException(nameof(args));
            }

            if (Db.Features.Any(f => f.Name == args.Name && f.Id != featureId))
            {
                throw new ArgumentException($"A feature with name '{args.Name}' already exists");
            }

            var feature = GetFeature(featureId, loadParent: true, loadChildren: true, loadGroups: true);

            if (feature == null)
            {
                throw new ResourceNotFoundException <Feature>(featureId);
            }

            var newParent = args.Parent.HasValue ? GetFeature(args.Parent.Value, loadChildren: true) : null;

            if (newParent == null && args.Parent.HasValue)
            {
                throw new ResourceNotFoundException <Feature>(args.Parent.Value);
            }

            // ensure that the new parent is not a descendant of or equal to the feature to be updated
            // (this would create a cycle destroying the tree structure)
            if (IsDescendantOrEqual(newParent, feature))
            {
                if (args.Parent != null)
                {
                    throw new InvalidOperationException($"Changing the parent of '{featureId}' to '{args.Parent.Value}' would destroy the tree structure because '{args.Parent.Value}' is a descendant of or the same as '{featureId}'");
                }
            }

            // 1) update name
            feature.Name = args.Name;

            // 2) detach from old parent
            feature.Parent?.Children.Remove(feature);

            // 3) attach to new parent
            newParent?.Children.Add(feature);
            feature.Parent = newParent;

            Db.SaveChanges();
        }