public Envelope <User> Register([FromBody] Envelope <Registration> registrationEnvelope)
        {
            EnsureModelValid();
            var login = registrationEnvelope.Content;

            // make sure the user doesn't already exist.
            if (_dbContext.Users.Any(x => x.Username == login.Username))
            {
                ModelState.AddModelError("username", "A user with the same username already exists");
            }
            if (_dbContext.Users.Any(x => x.Email == login.Email))
            {
                ModelState.AddModelError("username", "A user with the same email address already exists");
            }

            EnsureModelValid();

            Data.User dbUser = new Data.User
            {
                Email    = login.Email,
                Username = login.Username,
                Password = _authentication.HashPassword(login.Password)
            };
            _dbContext.Users.Add(dbUser);
            _dbContext.SaveChanges();

            var token = _authentication.GenerateToken(new MinimalUser
            {
                Username = login.Username,
                Created  = DateTime.UtcNow
            });

            return(UserFromDbUser(dbUser, token));
        }
        public Envelope <Comment> NewComment(string slug, [FromBody] Envelope <NewComment> comment)
        {
            EnsureModelValid();

            var dbArticleId = _dbContext.Articles.AsNoTracking()
                              .Where(x => x.Slug == slug)
                              .Select(x => x.Id)
                              .FirstOrDefault();

            var dbUser = _dbContext.Users.AsNoTracking()
                         .Where(x => x.Username == Username)
                         .FirstOrDefault();

            if (dbArticleId == 0 || dbUser == null)
            {
                throw NotFoundException();
            }

            var dbComment = new Data.Comment
            {
                ArticleId = dbArticleId,
                AuthorId  = dbUser.Id,
                Body      = comment.Content.Body,
                CreatedAt = DateTime.UtcNow,
                UpdatedAt = DateTime.UtcNow
            };

            _dbContext.Comments.Add(dbComment);
            _dbContext.SaveChanges();

            return(new Envelope <Comment>
            {
                EnvelopePropertyName = "comment",
                Content = new Comment
                {
                    Author = new Profile
                    {
                        Bio = dbUser.Bio,
                        Following = false,
                        Image = dbUser.Image,
                        Username = dbUser.Username
                    },
                    Body = dbComment.Body,
                    CreatedAt = dbComment.CreatedAt,
                    Id = dbComment.CommentId,
                    UpdatedAt = dbComment.UpdatedAt
                }
            });
        }
        public Envelope <Profile> Follow(string username)
        {
            if (string.IsNullOrEmpty(username) || username.Length < 3)
            {
                ModelState.AddModelError("username", "Username is invalid.");
            }
            else if (string.Equals(username, Username, StringComparison.OrdinalIgnoreCase))
            {
                ModelState.AddModelError("username", "You cannot follow yourself.");
            }
            EnsureModelValid();

            var user = _dbContext.Users.Where(u => u.Username == username)
                       .Select(u => new Profile
            {
                Bio       = u.Bio,
                Following = Username != null ? u.Followers.Any(f => f.FollowingUser.Username == Username) : false,
                Image     = u.Image,
                Username  = u.Username,
            }).FirstOrDefault();

            if (user == null)
            {
                throw NotFoundException();
            }
            else
            {
                if (!user.Following)
                {
                    _dbContext.Follows.Add(new Data.Follow
                    {
                        FollowingUserId = _dbContext.Users.Where(u => u.Username == Username).Select(u => u.Id).Single(),
                        FollowedUserId  = _dbContext.Users.Where(u => u.Username == username).Select(u => u.Id).Single()
                    });
                    _dbContext.SaveChanges();
                    user.Following = true;
                }

                return(new Envelope <Profile>
                {
                    EnvelopePropertyName = "profile",
                    Content = user
                });
            }
        }
        public Envelope <Article> CreateArticle([FromBody] Envelope <NewArticle> articleEnvelope)
        {
            EnsureModelValid();

            var article = articleEnvelope.Content;

            if (article.TagList.Any(string.IsNullOrEmpty))
            {
                ModelState.AddModelError("TagList", "There were blank tags in the tag list");
            }
            if (article.TagList.Any(x => x.Length > 100))
            {
                ModelState.AddModelError("TagList", "Some of the tags were too long");
            }

            EnsureModelValid();

            string slug   = GenerateSlug(article.Title);
            var    author = _dbContext.Users.Single(u => u.Username == Username);

            Data.Tag[] dbTags = article.TagList.Distinct(StringComparer.OrdinalIgnoreCase).Select(t => new Data.Tag {
                TagName = t
            }).ToArray();
            var dbArticle = new Data.Article
            {
                Author      = author,
                Body        = article.Body,
                CreatedAt   = DateTime.UtcNow,
                Description = article.Description,
                Slug        = slug,
                Title       = article.Title,
                UpdatedAt   = DateTime.UtcNow,
                Tags        = dbTags
            };

            _dbContext.Articles.Add(dbArticle);
            _dbContext.SaveChanges();

            return(new Envelope <Article>
            {
                EnvelopePropertyName = "article",
                Content = new Article
                {
                    Author = new Profile
                    {
                        Bio = author.Bio,
                        Following = false,
                        Image = author.Image,
                        Username = author.Username
                    },
                    Body = dbArticle.Body,
                    CreatedAt = dbArticle.CreatedAt,
                    Description = dbArticle.Description,
                    Favorited = false,
                    FavoritesCount = 0,
                    Slug = dbArticle.Slug,
                    TagList = dbArticle.Tags.Select(z => z.TagName).ToArray(),
                    Title = dbArticle.Title,
                    UpdatedAt = dbArticle.UpdatedAt
                }
            });
        }