Added forum validation after users registration

master
Zequez 2015-08-06 06:06:32 -03:00
parent 898a8f6ccd
commit d069a4172d
18 changed files with 277 additions and 119 deletions

View File

@ -48,7 +48,7 @@ class ApplicationController < ActionController::Base
end
def configure_devise_permitted_parameters
devise_parameter_sanitizer.for(:sign_up).push(:name, :email)
devise_parameter_sanitizer.for(:sign_up).push(:email, :forum_name)
devise_parameter_sanitizer.for(:sign_in).push(:login)
devise_parameter_sanitizer.for(:account_update)
end

View File

@ -1,10 +1,15 @@
class ForumValidationsController < ApplicationController
load_and_authorize_resource :forum_validation, except: :update
def create
@forum_validation = ForumValidation.new resource_params
@forum_validation.save! # server error if it fails, shouldn't happen
pm_sent = @forum_validation.send_pm
flash[:error] = I18n.t('forum_validations.flash.create.pm_error') unless pm_sent
redirect_to @forum_validation
if current_user.forum_validation
redirect_to current_user.forum_validation
else
@forum_validation.save! # server error if it fails, shouldn't happen
pm_sent = @forum_validation.send_pm
flash[:error] = I18n.t('forum_validations.flash.create.pm_error') unless pm_sent
redirect_to @forum_validation
end
end
def update
@ -27,9 +32,24 @@ class ForumValidationsController < ApplicationController
end
def new
if current_user.forum_validation
if current_user.forum_validation.validated?
redirect_to root_url
else
redirect_to forum_validation_url(current_user.forum_validation)
end
else
@forum_validation.author = Author.find_for_forum_validation(current_user.forum_name)
end
end
private
def resource_params
params.require(:forum_validation).permit(:author_id, :user_id)
params
.require(:forum_validation)
.permit(:author_id)
.merge(user_id: (current_user.id if current_user))
end
end

View File

@ -1,23 +1,34 @@
# https://github.com/plataformatec/devise/blob/master/app/controllers/devise/registrations_controller.rb
class Users::RegistrationsController < Devise::RegistrationsController
def create
@user = User.where(autogenerated: true).where('lower(name) = ?', sign_up_params[:name].downcase).first
if @user
@user.email = nil
@user.password = nil
@user.assign_attributes(sign_up_params)
@user.autogenerated = false
self.resource = @user
if @user.save
sign_up(:user, @user)
render :signed_up_autogenerated
else
clean_up_passwords @user
set_minimum_password_length
respond_with @user
end
# def create
# super{ |res| @user = res }
# @user = User.create
# @user = User.where(autogenerated: true).where('lower(name) = ?', sign_up_params[:name].downcase).first
# if @user
# @user.email = nil
# @user.password = nil
# @user.assign_attributes(sign_up_params)
# @user.autogenerated = false
# self.resource = @user
# if @user.save
# sign_up(:user, @user)
# render :signed_up_autogenerated
# else
# clean_up_passwords @user
# set_minimum_password_length
# respond_with @user
# end
# else
# super # Continue with regular registration
# end
# end
def after_sign_up_path_for(user)
if user.forum_name.present? and Author.find_for_forum_validation(user.forum_name)
new_forum_validation_path
else
super # Continue with regular registration
super(user)
end
end
end

View File

@ -11,6 +11,7 @@ class Ability
else
can(:read, Mod) { |mod| mod.visible }
if user.is_registered?
can :manage, ForumValidation, user_id: user.id
can :read, Bookmark, user_id: user.id
can :create, Bookmark
can :destroy, Bookmark, user_id: user.id

View File

@ -18,6 +18,10 @@ class Author < ActiveRecord::Base
find_by_slug normalize_friendly_id(name)
end
def self.find_for_forum_validation(forum_name)
where.not(forum_name: '').find_by_slugged_name(forum_name)
end
### Callbacks
#################

View File

@ -10,11 +10,14 @@ class User < ActiveRecord::Base
friendly_id :name, use: [:slugged, :finders]
auto_strip_attributes :forum_name, squish: true, nullify: false
has_many :mods, dependent: :nullify, foreign_key: :author_id
has_many :owned_mods, class_name: 'Mod', foreign_key: :author_id, dependent: :nullify # We'll change it to User#owner_id eventually
has_many :bookmarks
has_many :bookmarked_mods, through: :bookmarks, source: :mod
has_one :author
has_one :forum_validation
### Scopes
#################
@ -34,17 +37,15 @@ class User < ActiveRecord::Base
### Callbacks
#################
before_validation do
self.name = name.strip.squeeze(' ')
end
### Validations
#################
validates :name, presence: true,
format: { with: /\A[[:alnum:]\-_\. ]+\Z/i },
uniqueness: { case_sensitive: false },
length: { minimum: 2, maximum: 50 }
# validates :name, presence: true,
# format: { with: /\A[[:alnum:]\-_\. ]+\Z/i },
# uniqueness: { case_sensitive: false },
# length: { minimum: 2, maximum: 50 }
validates :forum_name, allow_blank: true, uniqueness: { case_sensitive: false }
### Initializers
#################

View File

@ -0,0 +1,12 @@
%h1 Forum account validation
The #{@forum_validation.author.forum_name} forum account has the following mods associated:
- @forum_validation.author.mods.each do |mod|
= mod.name
= semantic_form_for @forum_validation do |f|
= f.inputs do
= f.input :author_id, as: :hidden
= f.actions do
= f.action :submit

View File

@ -20,9 +20,8 @@
= f.semantic_errors
= f.inputs do
= f.input :email
= f.input :name
= f.input :forum_name
= f.input :password
= f.input :password_confirmation, required: true
= f.input :remember_me, as: :boolean, required: false
= redirect_to_input(f)
= f.actions do

View File

@ -68,8 +68,9 @@ en:
download_url: Release download URL
user:
login: Email or username
login: Email
name: Username
forum_name: Factorio Forum account name
hints:
mod:
@ -81,6 +82,8 @@ en:
imgur: "For an individual picture, not and album"
mod_file:
download_url: "Please use this instead of the attachment when possible, specially for large files"
users:
forum_name: If there are any mods associated with the account, we'll transfer them to you
placeholders:
mod:

View File

@ -85,7 +85,7 @@ Rails.application.routes.draw do
resources :mods, path: '/', only: :index
end
resources :forum_validations, path: 'forum-validations', only: [:show, :create] do
resources :forum_validations, path: 'forum-validations', only: [:new, :show, :create] do
member do
get '/validate', to: 'forum_validations#update'
end

View File

@ -0,0 +1,5 @@
class AddForumNameToUsers < ActiveRecord::Migration
def change
add_column :users, :forum_name, :string, default: '', null: false
end
end

View File

@ -11,7 +11,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20150806015412) do
ActiveRecord::Schema.define(version: 20150806060622) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@ -313,6 +313,7 @@ ActiveRecord::Schema.define(version: 20150806015412) do
t.string "name"
t.string "slug"
t.boolean "autogenerated", default: false, null: false
t.string "forum_name", default: "", null: false
end
add_index "users", ["email"], name: "index_users_on_email", unique: true, using: :btree

View File

@ -1,10 +1,11 @@
describe ForumValidationsController, type: :controller do
describe 'POST create' do
it 'should create a new ForumValidation with the corresponding author and user' do
it 'should create a new ForumValidation with the current user and given author' do
user = create :user
author = create :author
sign_in user
expect_any_instance_of(ForumValidation).to receive(:send_pm).and_return true
post :create, forum_validation: { user_id: user.id, author_id: author.id }
post :create, forum_validation: { author_id: author.id }
fv = ForumValidation.first
expect(fv.user).to eq user
expect(fv.author).to eq author
@ -14,19 +15,38 @@ describe ForumValidationsController, type: :controller do
end
it 'should throw a server error with invalid parameters' do
post :create, forum_validation: { user_id: 1234, author_id: 4321 }
user = create :user
sign_in user
post :create, forum_validation: { user_id: user.id, author_id: 4321 }
expect(response).to have_http_status :bad_request
end
it 'should redirect with an error flash message if the validation fails' do
user = create :user
author = create :author
sign_in user
expect_any_instance_of(ForumValidation).to receive(:send_pm).and_return false
post :create, forum_validation: { user_id: user.id, author_id: author.id }
post :create, forum_validation: { author_id: author.id }
fv = ForumValidation.first
expect(flash[:error]).to eq I18n.t('forum_validations.flash.create.pm_error')
expect(response).to redirect_to fv
end
it 'should be unauthorized while not logged in' do
author = create :author
post :create, forum_validation: { author_id: author.id }
expect(response).to have_http_status :unauthorized
end
it 'should redirect to the existing validation if the user already has one' do
user = create :user
author = create :author
sign_in user
fv = create :forum_validation, user: user, author: author
expect_any_instance_of(ForumValidation).to_not receive(:send_pm)
post :create, forum_validation: { author_id: author.id }
expect(response).to redirect_to fv
end
end
# Yes, GET
@ -124,8 +144,50 @@ describe ForumValidationsController, type: :controller do
@m2 = create :mod, authors: [@fv.author]
@fv.associate_user_and_author!
@fv.user.give_ownership_of_authored!
sign_in @fv.user
get :show, id: @fv.id
expect(response).to have_http_status :success
expect(response).to render_template :show
end
end
describe 'GET new' do
context 'logged in user' do
it 'should just render the new form if it can be validated' do
author = create :author, forum_name: 'Potato', name: 'Potato'
sign_in create(:user, forum_name: 'Potato')
get :new
expect(assigns(:forum_validation).author).to eq author
expect(response).to render_template :new
end
it 'should redirect to the root if the user is already validated' do
author = create :author, forum_name: 'Potato', name: 'Potato'
user = create :user, forum_name: 'Potato'
create :forum_validation, author: author, user: user, validated: true
sign_in user
get :new
expect(response).to redirect_to root_path
end
it 'should redirect to the forum_validations#show if the user has a pending validation' do
author = create :author, forum_name: 'Potato', name: 'Potato'
user = create :user, forum_name: 'Potato'
fv = create :forum_validation, author: author, user: user, validated: false
sign_in user
get :new
expect(response).to redirect_to fv
end
end
context 'logged out user' do
it 'should redirect to login form' do
create :author, forum_name: 'Potato', name: 'Potato'
create :user, forum_name: 'Potato'
get :new
expect(response).to have_http_status :redirect
expect(response.location).to match new_user_session_path
end
end
end
end

View File

@ -7,48 +7,72 @@ describe Users::RegistrationsController, type: :controller do
it 'should create a new user with valid parameters' do
post :create, user: {
email: 'potato@salad.com',
name: 'Potato',
forum_name: 'Potato',
password: '12345678',
password_confirmation: '12345678'
}
user = User.first
expect(user.email).to eq 'potato@salad.com'
expect(user.name).to eq 'Potato'
expect(user.forum_name).to eq 'Potato'
expect(response).to redirect_to root_path
end
it 'should still create a new user without a forum name' do
post :create, user: {
email: 'potato@salad.com',
forum_name: '',
password: '12345678',
password_confirmation: '12345678'
}
user = User.first
expect(user.email).to eq 'potato@salad.com'
expect(user.forum_name).to eq ''
expect(response).to redirect_to root_path
end
it 'should add errors to the user with invalid parameters' do
post :create, user: {
email: 'potatosalad.com',
name: '',
forum_name: '',
password: '1278',
password_confirmation: '12345678'
}
expect(User.all).to be_empty
user = assigns(:user)
expect(user.errors[:email]).to_not be_empty
expect(user.errors[:name]).to_not be_empty
expect(user.errors[:forum_name]).to be_empty
expect(user.errors[:password]).to_not be_empty
expect(user.errors[:password_confirmation]).to_not be_empty
expect(response).to render_template :new
end
context 'the user was autogenerated' do
it 'should use the same user and replace the email and password' do
user = create :user,
name: 'Potato',
email: 'potato@salad.com',
password: 'rsarsarsa',
autogenerated: true
context 'the user used a forum_name associated with an author' do
it 'should redirect to forum_validations#new after creating the user' do
create :author, name: 'Potato', forum_name: 'Potato'
post :create, user: {
name: 'Potato',
email: 'potato2@salad.com',
password: '12345678'
email: 'potato@salad.com',
forum_name: 'Potato',
password: '12345678',
password_confirmation: '12345678'
}
user.reload
expect(assigns(:user)).to eq user
expect(user.name).to eq 'Potato'
expect(user.email).to eq 'potato2@salad.com'
expect(user.valid_password?('12345678')).to eq true
expect(user.autogenerated).to eq false
expect(response).to redirect_to new_forum_validation_path
end
end
context 'the user used a forum_name not associated with any author' do
it 'should redirect to the root as usual' do
create :author, name: 'Potato', forum_name: 'Potato'
post :create, user: {
email: 'potato@salad.com',
forum_name: 'rsarsarsa',
password: '12345678',
password_confirmation: '12345678'
}
expect(response).to redirect_to root_path
end
end
end

View File

@ -3,6 +3,7 @@ feature 'Common sign in and sign up form everywhere' do
visit '/users/login'
expect(page).to have_field 'user_login'
expect(page).to_not have_field 'user_email'
expect(page).to_not have_field 'user_forum_name'
expect(page).to_not have_field 'user_name'
expect(page).to have_field 'user_password'
expect(page).to_not have_field 'user_password_confirmation'
@ -10,9 +11,10 @@ feature 'Common sign in and sign up form everywhere' do
page.find('[for="identify_register"]').click
expect(page).to_not have_field 'user_login'
expect(page).to have_field 'user_email'
expect(page).to have_field 'user_name'
expect(page).to have_field 'user_forum_name'
expect(page).to_not have_field 'user_name'
expect(page).to have_field 'user_password'
expect(page).to have_field 'user_password_confirmation'
expect(page).to_not have_field 'user_password_confirmation'
expect(page).to have_field 'user_remember_me'
end
end

View File

@ -42,9 +42,7 @@ feature 'Redirect to the previous page the user was after login' do
expect(current_path).to eq '/users/register'
within('#new_registration') do
fill_in 'user_email', with: 'banana@split.com'
fill_in 'user_name', with: 'PotatoHead'
fill_in 'user_password', with: 'rsarsarsa'
fill_in 'user_password_confirmation', with: 'rsarsarsa'
click_button 'Register'
end
expect(current_path).to eq '/mods/hey'
@ -56,20 +54,14 @@ feature 'Redirect to the previous page the user was after login' do
click_link 'Register'
expect(current_path).to eq '/users/register'
within('#new_registration') do
fill_in 'user_email', with: 'banana@split.com'
fill_in 'user_name', with: 'INVALID USERNAME!!!'
fill_in 'user_email', with: 'bansplit.com'
fill_in 'user_password', with: 'rsarsarsa'
fill_in 'user_password_confirmation', with: 'rsarsarsa'
fill_in 'user_email', with: 'banana@split.com'
click_button 'Register'
end
expect(current_path).to eq '/users'
within('#new_registration') do
fill_in 'user_email', with: 'banana@split.com'
fill_in 'user_name', with: 'PotatoHead'
fill_in 'user_password', with: 'rsarsarsa'
fill_in 'user_password_confirmation', with: 'rsarsarsa'
fill_in 'user_email', with: 'banana@split.com'
click_button 'Register'
end
expect(current_path).to eq '/mods/hey'

View File

@ -9,22 +9,25 @@ describe User, :type => :model do
it { is_expected.to respond_to :slug }
it { is_expected.to respond_to :autogenerated }
it { is_expected.to respond_to :login }
it { is_expected.to respond_to :forum_name }
it { is_expected.to respond_to :owned_mods }
it { is_expected.to respond_to :bookmarks }
it { is_expected.to respond_to :bookmarked_mods }
it { is_expected.to respond_to :author }
it { is_expected.to respond_to :forum_validation }
its('owned_mods.build') { is_expected.to be_kind_of Mod }
its('bookmarks.build') { is_expected.to be_kind_of Bookmark }
its('bookmarked_mods.build') { is_expected.to be_kind_of Mod }
its('build_author') { is_expected.to be_kind_of Author }
its('build_forum_validation'){ is_expected.to be_kind_of ForumValidation }
describe 'validations' do
it 'should not allow user without name' do
user = build :user, name: ''
expect(user).to be_invalid
end
# it 'should not allow user without name' do
# user = build :user, name: ''
# expect(user).to be_invalid
# end
it 'should not allow user without email' do
user = build :user, email: ''
@ -41,52 +44,58 @@ describe User, :type => :model do
expect(user).to be_invalid
end
it 'should allow spaces in the name' do
user = build :user, name: 'Potato Head'
expect(user).to be_valid
end
it 'should strip extra spaces and sqeeze them automatically' do
user = build :user, name: ' Potato Head '
expect(user).to be_valid
expect(user.name).to eq 'Potato Head'
end
it 'should not allow users with the same name' do
create :user, name: 'HeyHeyNanana'
user2 = build :user, name: 'HeyHeyNanana'
it 'should not allow 2 users with the same #forum_name' do
create :user, forum_name: 'HeyHeyNanana'
user2 = build :user, forum_name: 'HeyHeyNanana'
expect(user2).to be_invalid
end
it 'should not allow users with the same name with different cases' do
create :user, name: 'HeyHeyNanana'
user2 = build :user, name: 'heyheynanana'
expect(user2).to be_invalid
end
it 'should not allow names shorter than 2 characters' do
user = build :user, name: 'a'
expect(user).to be_invalid
end
it 'should allow names of 2 characters' do
user = build :user, name: '22'
expect(user).to be_valid
end
it 'should not allow names longer than 50 characters' do
user = build :user, name: 'a'*51
expect(user).to be_invalid
end
it 'should allow names of 50 characters' do
user = build :user, name: 'a'*50
expect(user).to be_valid
end
it 'should be valid with alphanumeric characters, spaces, dashes, underscores, dots or spaces' do
expect(build(:user, name: 'Zeq.mán123- _Potatoí')).to be_valid
end
# it 'should allow spaces in the name' do
# user = build :user, name: 'Potato Head'
# expect(user).to be_valid
# end
#
# it 'should strip extra spaces and sqeeze them automatically' do
# user = build :user, name: ' Potato Head '
# expect(user).to be_valid
# expect(user.name).to eq 'Potato Head'
# end
#
# it 'should not allow users with the same name' do
# create :user, name: 'HeyHeyNanana'
# user2 = build :user, name: 'HeyHeyNanana'
# expect(user2).to be_invalid
# end
#
# it 'should not allow users with the same name with different cases' do
# create :user, name: 'HeyHeyNanana'
# user2 = build :user, name: 'heyheynanana'
# expect(user2).to be_invalid
# end
#
# it 'should not allow names shorter than 2 characters' do
# user = build :user, name: 'a'
# expect(user).to be_invalid
# end
#
# it 'should allow names of 2 characters' do
# user = build :user, name: '22'
# expect(user).to be_valid
# end
#
# it 'should not allow names longer than 50 characters' do
# user = build :user, name: 'a'*51
# expect(user).to be_invalid
# end
#
# it 'should allow names of 50 characters' do
# user = build :user, name: 'a'*50
# expect(user).to be_valid
# end
#
# it 'should be valid with alphanumeric characters, spaces, dashes, underscores, dots or spaces' do
# expect(build(:user, name: 'Zeq.mán123- _Potatoí')).to be_valid
# end
end
describe 'attributes' do

View File

@ -0,0 +1,12 @@
describe 'forum_validations/new', type: :view do
it 'should render the mods associated with the author' do
fv = create :forum_validation
create :mod, authors: [fv.author], name: 'Potato'
create :mod, authors: [fv.author], name: 'Galaxy'
create :mod, authors: [fv.author], name: 'Simulator'
assign(:forum_validation, fv)
render
expect(rendered).to match(/Potato.*Galaxy.*Simulator/m)
expect(rendered).to have_selector("#forum_validation_author_id[value=\"#{fv.author_id}\"]")
end
end