public HappeningDto AddUser(Guid happeningId, Guid userId, bool commitImmediately = true)
        {
            // Happening.Name later isn't 100% needed but this serves to make sure the specified Happening actually exists
            Happening happening = GetEnt(happeningId);

            // make sure the user hasn't already been added
            if (joinService.GetEnt(userId, happeningId) != null)
            {
                throw new HandledException(new ArgumentException("Cannot add a user already added to event"));
            }

            var userToAdd = userService.GetEntOrDefault(userId);

            if (userToAdd == null)
            {
                throw new HandledException(new ArgumentException("Cannot add a user that doesn't exist"));
            }

            // happening has to either be non-private, the logged in user doing the adding has to be the owner, or the logged in user has to be an admin
            User currentUser = loginService.GetCurrentUser();

            if (happening.IsPrivate && happening.ControllingUserId != currentUser.Id && currentUser.Role != UserRole.Admin)
            {
                throw new HandledException(new ArgumentException("Can only add a user to a happening if it is non-private, the current user is the owner, or is an admin"));
            }

            InvitationDto result = new InvitationDto()
            {
                HappeningId         = happeningId,
                UserId              = userId,
                UserName            = userToAdd.FriendlyName,
                ReminderXMinsBefore = 0,
                HappeningName       = happening.Name,
                Date      = happening.StartTime,
                Status    = RSVP.NoResponse.ToString(),
                IsPrivate = happening.IsPrivate
            };

            HappeningUser joinEntity = joinService.CreateEntity(result);

            happening.AllUsers.Add(joinEntity);

            if (commitImmediately)
            {
                SaveChanges();
                return(Get(happeningId));
            }
            else
            {
                HappeningDto projectedResult = DtoFromEntity(happening);
                projectedResult.AllUsers = projectedResult.AllUsers.Append(userId);
                return(projectedResult);
            }
        }
        public HappeningDto RemoveUser(Guid happeningId, Guid userId, bool commitImmediately = true)
        {
            // make sure the specified Happening actually exists
            Happening happening = GetEnt(happeningId);

            HappeningUser joinEntity = joinService.GetEnt(userId, happeningId);

            if (joinEntity == null)
            {
                throw new HandledException(new ArgumentException("Cannot remove a user that isn't attached to the event"));
            }

            // happening has to either be non-private, the logged in user doing the adding has to be the owner, or the logged in user has to be an admin
            User currentUser = loginService.GetCurrentUser();

            if (userId != currentUser.Id && happening.ControllingUserId != currentUser.Id && currentUser.Role != UserRole.Admin)
            {
                throw new HandledException(new ArgumentException("Can only remove a user from happening if the current user is the one being removed, is the owner, or is an admin"));
            }


            happening.AllUsers.Remove(joinEntity);
            joinService.DeleteEnt(joinEntity);

            if (commitImmediately)
            {
                SaveChanges();
                return(Get(happeningId));
            }
            else
            {
                HappeningDto projectedResult = DtoFromEntity(happening);
                projectedResult.AllUsers = projectedResult.AllUsers.Where(x => x != userId);
                return(projectedResult);
            }
        }