diff --git a/app/assets/stylesheets/pages/_error.scss b/app/assets/stylesheets/pages/_error.scss index e94f826..2915ced 100644 --- a/app/assets/stylesheets/pages/_error.scss +++ b/app/assets/stylesheets/pages/_error.scss @@ -25,6 +25,16 @@ background-color: #f39c12; } +.success { + @extend .error; + background-color: $brand-success; +} + +.notice { + @extend .error; + background-color: $brand-info; +} + [data-id="live-coder-finish-later"] { .warning { margin-top: 0; diff --git a/app/controllers/admin/auth_controller.rb b/app/controllers/admin/auth_controller.rb index a6db502..cb097fc 100644 --- a/app/controllers/admin/auth_controller.rb +++ b/app/controllers/admin/auth_controller.rb @@ -21,5 +21,44 @@ module Admin reset_session redirect_to admin_login_path end + + def reset_request + end + + def send_reset + user = User.find_by(email: request_params[:email]) + redirect_to(admin_reset_request_path) and return if user.nil? + + user.setup_reset + UserMailer.password_reset(user).deliver_now + redirect_to admin_reset_request_path, + success: "Reset request sent! Please check your email for instructions." + end + + def reset + user = User.find_by(reset_token: params[:reset_token]) + redirect_to(admin_reset_request_path) and return if user.nil? + end + + def reset_password + user = User.find_by(reset_token: params[:reset_token]) + redirect_to(admin_reset_request_path) and return if user.nil? + + if user.update(reset_params) + redirect_to admin_login_path, success: "Password has been reset. Please log in." + else + redirect_to admin_reset_request_path, flash: { error: "Password was not updated." } + end + end + + private + + def request_params + params.require(:auth).permit(:email) + end + + def reset_params + params.require(:auth).permit(:password, :password_confirmation) + end end end diff --git a/app/controllers/admin/profile_controller.rb b/app/controllers/admin/profile_controller.rb new file mode 100644 index 0000000..08f8f32 --- /dev/null +++ b/app/controllers/admin/profile_controller.rb @@ -0,0 +1,28 @@ +module Admin + class ProfileController < AdminController + def view + end + + def edit + @user = current_admin + end + + def update + @user = current_admin + + if @user.update_attributes(user_params) + redirect_to admin_profile_path, + flash: { success: "Sucessfully updated profile" } + else + flash[:error] = "Failed to update profile." + render :edit + end + end + + private + + def user_params + params.require(:user).permit(:name, :email, :password, :password_confirmation) + end + end +end diff --git a/app/controllers/admin/question_controller.rb b/app/controllers/admin/question_controller.rb index ee5a355..7ee4266 100644 --- a/app/controllers/admin/question_controller.rb +++ b/app/controllers/admin/question_controller.rb @@ -14,7 +14,7 @@ module Admin @question = Question.create(process_question_params) if @question.persisted? - redirect_to admin_questions_path, flash: { notice: "Sucessfully created question" } + redirect_to admin_questions_path, flash: { success: "Sucessfully created question" } else flash[:error] = "Failed to save question." render :new @@ -36,7 +36,7 @@ module Admin if @question.update_attributes(process_question_params) redirect_to admin_question_path(@question.to_i), - flash: { notice: "Sucessfully updated question" } + flash: { success: "Sucessfully updated question" } else flash[:error] = "Failed to update question." render :edit diff --git a/app/controllers/admin/user_controller.rb b/app/controllers/admin/user_controller.rb index 23c11dd..85b4e71 100644 --- a/app/controllers/admin/user_controller.rb +++ b/app/controllers/admin/user_controller.rb @@ -13,8 +13,8 @@ module Admin @user = User.create({ password: default_passwd }.merge(user_params.to_h)) if @user.persisted? - # TODO: UserMailer.welcome(@user, default_passwd).deliver_now - redirect_to admin_users_path, flash: { notice: "Sucessfully created user #{@user.name}" } + UserMailer.welcome(@user, default_passwd).deliver_now + redirect_to admin_users_path, flash: { success: "Sucessfully created user #{@user.name}" } else flash[:error] = "Failed to save user." render :new @@ -34,7 +34,7 @@ module Admin if @user.update_attributes(user_params) redirect_to admin_user_path(@user.to_i), - flash: { notice: "Sucessfully updated #{@user.name}" } + flash: { success: "Sucessfully updated #{@user.name}" } else flash[:error] = "Failed to update user." render :edit diff --git a/app/controllers/admin_controller.rb b/app/controllers/admin_controller.rb index 53313b0..37a79b4 100644 --- a/app/controllers/admin_controller.rb +++ b/app/controllers/admin_controller.rb @@ -1,6 +1,6 @@ class AdminController < ApplicationController layout 'admin' - before_action :authorize_admin, except: :styleguide + before_action :authorize_admin def dashboard @quizzes = Quiz.includes(:questions).all diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index e6bb02d..430edcd 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -1,6 +1,8 @@ class ApplicationController < ActionController::Base protect_from_forgery with: :exception + add_flash_types :warning, :success + def current_recruiter user_parms = { id: session[:user], role: %w(admin recruiter) } @current_recruiter ||= User.find_by(user_parms) if session[:user] diff --git a/app/controllers/recruiter_controller.rb b/app/controllers/recruiter_controller.rb index dcb145a..23a3238 100644 --- a/app/controllers/recruiter_controller.rb +++ b/app/controllers/recruiter_controller.rb @@ -16,7 +16,7 @@ class RecruiterController < ApplicationController if @candidate.persisted? CandidateMailer.welcome(@candidate).deliver_now RecruiterMailer.candidate_created(@candidate).deliver_now - redirect_to recruiter_path, flash: { notice: "Sucessfully created candidate #{@candidate.name}" } + redirect_to recruiter_path, flash: { success: "Sucessfully created candidate #{@candidate.name}" } else flash[:error] = "Failed to save candidate." render :form diff --git a/app/mailers/user_mailer.rb b/app/mailers/user_mailer.rb new file mode 100644 index 0000000..3ea1484 --- /dev/null +++ b/app/mailers/user_mailer.rb @@ -0,0 +1,12 @@ +class UserMailer < ApplicationMailer + def password_reset user + @user = user + mail to: user.email, subject: 'Password Reset' + end + + def welcome user, default_password + @user = user + @password = default_password + mail to: user.email, subject: "Skill Assesment Acount" + end +end diff --git a/app/models/user.rb b/app/models/user.rb index 1da0679..781cfac 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -5,4 +5,20 @@ class User < ApplicationRecord validates_presence_of :email validates_presence_of :name validates_presence_of :role + validates :reset_token, uniqueness: true, allow_nil: true + + def setup_reset + gen_reset_token + save + end + + private + + def gen_reset_token + loop do + self[:reset_token] = SecureRandom.urlsafe_base64(10) + self[:reset_timestamp] = DateTime.now + break unless User.exists?(reset_token: self[:reset_token]) + end + end end diff --git a/app/views/admin/auth/login.html.erb b/app/views/admin/auth/login.html.erb index b54def1..725a817 100644 --- a/app/views/admin/auth/login.html.erb +++ b/app/views/admin/auth/login.html.erb @@ -1,21 +1,19 @@ -
-

Admin Login

+<% + content_for :main_class, "intro_tpl" +%> - <% if flash[:error].present? %> -
<%= flash[:error] %>
- <% end %> +

Admin Login

- <%= form_for :auth, url: admin_login_path do |form| %> -
- <%= form.label :email %> - <%= form.email_field :email %> -
+<%= form_for :auth, url: admin_login_path do |form| %> +
+ <%= form.label :email %> + <%= form.email_field :email %> +
-
- <%= form.label :password %> - <%= form.password_field :password %> -
+
+ <%= form.label :password %> + <%= form.password_field :password %> +
- <%= submit_tag "Log in" %> - <% end %> -
+ <%= submit_tag "Log in" %> +<% end %> diff --git a/app/views/admin/auth/reset.html.erb b/app/views/admin/auth/reset.html.erb new file mode 100644 index 0000000..2b1aee8 --- /dev/null +++ b/app/views/admin/auth/reset.html.erb @@ -0,0 +1,21 @@ +<% + content_for :main_class, "intro_tpl" +%> + +

Password Reset

+ +<%= form_for :auth, url: admin_reset_password_path do |form| %> + <%= hidden_field_tag :reset_token, params[:reset_token] %> + +
+ <%= form.label :password %> + <%= form.password_field :password %> +
+ +
+ <%= form.label :password_confirmation %> + <%= form.password_field :password_confirmation %> +
+ + <%= submit_tag "Reset Password" %> +<% end %> diff --git a/app/views/admin/auth/reset_request.html.erb b/app/views/admin/auth/reset_request.html.erb new file mode 100644 index 0000000..bb23fb8 --- /dev/null +++ b/app/views/admin/auth/reset_request.html.erb @@ -0,0 +1,14 @@ +<% + content_for :main_class, "intro_tpl" +%> + +

Password Reset

+<%= form_for :auth, url: admin_send_reset_path do |form| %> + +
+ <%= form.label :email %> + <%= form.email_field :email %> +
+ + <%= submit_tag "Request Password Reset" %> +<% end %> diff --git a/app/views/admin/dashboard.html.erb b/app/views/admin/dashboard.html.erb index c19052d..9939146 100644 --- a/app/views/admin/dashboard.html.erb +++ b/app/views/admin/dashboard.html.erb @@ -2,17 +2,14 @@ content_for :section_title, "Admin Dashboard" %> -
-
-

Quizzes

- <%= render partial: 'admin/quiz/table_list', locals: { quizzes: @quizzes } %> - <%= link_to('New Quiz', admin_new_quiz_path, { class: 'btn' }) %> -
+
+

Quizzes

+ <%= render partial: 'admin/quiz/table_list', locals: { quizzes: @quizzes } %> + <%= link_to('New Quiz', admin_new_quiz_path, { class: 'btn' }) %> +
-
-

Users

- <%= render partial: 'admin/user/table_list', locals: { users: @users } %> - <%= link_to('New User', admin_new_user_path, { class: 'btn' }) %> -
- -
+
+

Users

+ <%= render partial: 'admin/user/table_list', locals: { users: @users } %> + <%= link_to('New User', admin_new_user_path, { class: 'btn' }) %> +
diff --git a/app/views/admin/profile/edit.html.erb b/app/views/admin/profile/edit.html.erb new file mode 100644 index 0000000..d1014d2 --- /dev/null +++ b/app/views/admin/profile/edit.html.erb @@ -0,0 +1,28 @@ +<% + content_for :section_title, "Edit: #{@user.name}" +%> + +<%= render partial: 'shared/form_model_errors', locals: {obj: @user} %> +<%= form_for @user, url: admin_profile_url, method: :post do |form| %> +
+ <%= form.label :name, "Full Name" %> + <%= form.text_field :name %> +
+ +
+ <%= form.label :email, "eMail" %> + <%= form.email_field :email %> +
+ +
+ <%= form.label :password, "New Password" %> + <%= form.password_field :password %> +
+ +
+ <%= form.label :password_confirmation, "New Password Confirmation" %> + <%= form.password_field :password_confirmation %> +
+ + <%= form.submit %> +<% end %> diff --git a/app/views/admin/profile/view.html.erb b/app/views/admin/profile/view.html.erb new file mode 100644 index 0000000..92ff9b1 --- /dev/null +++ b/app/views/admin/profile/view.html.erb @@ -0,0 +1,8 @@ +<% + content_for :section_title, "Profile" +%> + +

Name: <%= current_admin.name %>

+

email: <%= current_admin.email %>

+

Role: <%= current_admin.role %>

+<%= link_to('Edit', admin_edit_profile_path, { class: 'btn' }) %> diff --git a/app/views/admin/question/edit.html.erb b/app/views/admin/question/edit.html.erb index baea6e8..6428daa 100644 --- a/app/views/admin/question/edit.html.erb +++ b/app/views/admin/question/edit.html.erb @@ -2,8 +2,5 @@ content_for :section_title, "Questions" %> -
-

<%= @question.quiz.name %>

- - <%= render partial: 'form', locals: {question: @question, action: admin_update_question_path } %> -
+

<%= @question.quiz.name %>

+<%= render partial: 'form', locals: {question: @question, action: admin_update_question_path } %> diff --git a/app/views/admin/question/index.html.erb b/app/views/admin/question/index.html.erb index 8ec115b..f6f17b0 100644 --- a/app/views/admin/question/index.html.erb +++ b/app/views/admin/question/index.html.erb @@ -2,11 +2,9 @@ content_for :section_title, "Questions" %> -
- <% quizzes = @questions.group_by{ |q| q.quiz.name } %> - <% quizzes.each do |quiz, questions| %> -

<%= quiz %>

- <%= render partial: 'admin/question/table_list', locals: { questions: questions } %> - <%= link_to('Edit Quiz', admin_quiz_path(questions.first.quiz.to_i), { class: 'btn' }) %> - <% end %> -
+<% quizzes = @questions.group_by{ |q| q.quiz.name } %> +<% quizzes.each do |quiz, questions| %> +

<%= quiz %>

+ <%= render partial: 'admin/question/table_list', locals: { questions: questions } %> + <%= link_to('Edit Quiz', admin_quiz_path(questions.first.quiz.to_i), { class: 'btn' }) %> +<% end %> diff --git a/app/views/admin/question/new.html.erb b/app/views/admin/question/new.html.erb index 8bc7a68..351b388 100644 --- a/app/views/admin/question/new.html.erb +++ b/app/views/admin/question/new.html.erb @@ -2,6 +2,4 @@ content_for :section_title, "New Question" %> -
- <%= render partial: 'form', locals: {question: @question, action: admin_create_question_path } %> -
+<%= render partial: 'form', locals: {question: @question, action: admin_create_question_path } %> diff --git a/app/views/admin/question/view.html.erb b/app/views/admin/question/view.html.erb index 24bba3e..c39789c 100644 --- a/app/views/admin/question/view.html.erb +++ b/app/views/admin/question/view.html.erb @@ -2,37 +2,35 @@ content_for :section_title, "Question for #{@question.quiz.name}" %> -
- - - - - - - - - - - - - - - - - -
Category<%= @question.category %>
Type<%= @question.input_type %>
Sort<%= @question.sort %>
- <%= check_box_tag 'question_active', nil, @question.active?, {disabled: true} %> - <%= label_tag 'question_active', 'Active' %> -
+ + + + + + + + + + + + + + + + + +
Category<%= @question.category %>
Type<%= @question.input_type %>
Sort<%= @question.sort %>
+ <%= check_box_tag 'question_active', nil, @question.active?, {disabled: true} %> + <%= label_tag 'question_active', 'Active' %> +
- Question -

<%= @question.question %>

+Question +

<%= @question.question %>

- <%= fields_for @question do |fields| %> - <%= render partial: "admin/question/#{@question.input_type}", locals: {question: @question, disable: true, fields: fields } %> - <% end %> +<%= fields_for @question do |fields| %> + <%= render partial: "admin/question/#{@question.input_type}", locals: {question: @question, disable: true, fields: fields } %> +<% end %> - <%= link_to('Edit', admin_edit_question_path(@question.to_i), { class: 'btn' }) %> +<%= link_to('Edit', admin_edit_question_path(@question.to_i), { class: 'btn' }) %> - <%= link_to('View Quiz', admin_quiz_path(@question.quiz_id), { class: 'btn' }) %> -
+<%= link_to('View Quiz', admin_quiz_path(@question.quiz_id), { class: 'btn' }) %> diff --git a/app/views/admin/quiz/edit.html.erb b/app/views/admin/quiz/edit.html.erb index a67e234..bf23b0e 100644 --- a/app/views/admin/quiz/edit.html.erb +++ b/app/views/admin/quiz/edit.html.erb @@ -2,6 +2,4 @@ content_for :section_title, "Edit: #{@quiz.name}" %> -
- <%= render partial: 'form', locals: { quiz: @quiz, action: admin_update_quiz_path } %> -
+<%= render partial: 'form', locals: { quiz: @quiz, action: admin_update_quiz_path } %> diff --git a/app/views/admin/quiz/index.html.erb b/app/views/admin/quiz/index.html.erb index 70b8cf2..1bce4e8 100644 --- a/app/views/admin/quiz/index.html.erb +++ b/app/views/admin/quiz/index.html.erb @@ -2,7 +2,5 @@ content_for :section_title, "Quizzes" %> -
- <%= render partial: 'admin/quiz/table_list', locals: { quizzes: @quizzes } %> - <%= link_to('New Quiz', admin_new_quiz_path, { class: 'btn' }) %> -
+<%= render partial: 'admin/quiz/table_list', locals: { quizzes: @quizzes } %> +<%= link_to('New Quiz', admin_new_quiz_path, { class: 'btn' }) %> diff --git a/app/views/admin/quiz/new.html.erb b/app/views/admin/quiz/new.html.erb index 2d0dd11..2bb5726 100644 --- a/app/views/admin/quiz/new.html.erb +++ b/app/views/admin/quiz/new.html.erb @@ -2,6 +2,4 @@ content_for :section_title, "New Quiz" %> -
- <%= render partial: 'form', locals: { quiz: @quiz, action: admin_create_quiz_path } %> -
+<%= render partial: 'form', locals: { quiz: @quiz, action: admin_create_quiz_path } %> diff --git a/app/views/admin/quiz/view.html.erb b/app/views/admin/quiz/view.html.erb index 21eb321..f37b865 100644 --- a/app/views/admin/quiz/view.html.erb +++ b/app/views/admin/quiz/view.html.erb @@ -2,14 +2,10 @@ content_for :section_title, "#{@quiz.name}" %> -
-

<%= @quiz.name %>

-

<%= @quiz.dept %>

-

<%= @quiz.unit %>

- <%= link_to('Edit', admin_edit_quiz_path(@quiz.to_i), { class: 'btn' }) %> -
+

<%= @quiz.name %>

+

<%= @quiz.dept %>

+

<%= @quiz.unit %>

+<%= link_to('Edit', admin_edit_quiz_path(@quiz.to_i), { class: 'btn' }) %> -
- <%= render partial: 'admin/question/table_list', locals: { questions: @quiz.questions, disable: true } %> - <%= link_to('New Question', admin_new_question_path, { class: 'btn' }) %> -
+<%= render partial: 'admin/question/table_list', locals: { questions: @quiz.questions, disable: true } %> +<%= link_to('New Question', admin_new_question_path, { class: 'btn' }) %> diff --git a/app/views/admin/user/edit.html.erb b/app/views/admin/user/edit.html.erb index 0ccc724..262ff3c 100644 --- a/app/views/admin/user/edit.html.erb +++ b/app/views/admin/user/edit.html.erb @@ -2,6 +2,4 @@ content_for :section_title, "Edit: #{@user.name}" %> -
- <%= render partial: 'form', locals: {user: @user, action: admin_update_user_path } %> -
+<%= render partial: 'form', locals: {user: @user, action: admin_update_user_path } %> diff --git a/app/views/admin/user/index.html.erb b/app/views/admin/user/index.html.erb index 3092e28..2598812 100644 --- a/app/views/admin/user/index.html.erb +++ b/app/views/admin/user/index.html.erb @@ -2,8 +2,6 @@ content_for :section_title, "Users" %> -
-

Users

- <%= render partial: 'admin/user/table_list', locals: { users: @users } %> - <%= link_to('New User', admin_new_user_path, { class: 'btn' }) %> -
+

Users

+<%= render partial: 'admin/user/table_list', locals: { users: @users } %> +<%= link_to('New User', admin_new_user_path, { class: 'btn' }) %> diff --git a/app/views/admin/user/new.html.erb b/app/views/admin/user/new.html.erb index dc70d47..0958f6a 100644 --- a/app/views/admin/user/new.html.erb +++ b/app/views/admin/user/new.html.erb @@ -2,6 +2,4 @@ content_for :section_title, "New User" %> -
- <%= render partial: 'form', locals: {user: @user, action: admin_create_user_path } %> -
+<%= render partial: 'form', locals: {user: @user, action: admin_create_user_path } %> diff --git a/app/views/admin/user/view.html.erb b/app/views/admin/user/view.html.erb index caf2c25..0bd3f52 100644 --- a/app/views/admin/user/view.html.erb +++ b/app/views/admin/user/view.html.erb @@ -2,9 +2,7 @@ content_for :section_title, "#{@user.name}" %> -
-

<%= @user.name %>

-

<%= mail_to(@user.email) %>

-

<%= @user.role %>

- <%= link_to('Edit', admin_edit_user_path(@user.to_i), { class: 'btn' }) %> -
+

<%= @user.name %>

+

<%= mail_to(@user.email) %>

+

<%= @user.role %>

+<%= link_to('Edit', admin_edit_user_path(@user.to_i), { class: 'btn' }) %> diff --git a/app/views/candidate_mailer/reminder.html.inky b/app/views/candidate_mailer/reminder.html.inky index 9919514..b0f87e4 100644 --- a/app/views/candidate_mailer/reminder.html.inky +++ b/app/views/candidate_mailer/reminder.html.inky @@ -8,8 +8,10 @@

You can return to the test here: - <%= link_to nil, root_url %>. + <%= link_to nil, login_url(@candidate.test_hash) %>.
+  
+ Or, visit <%= link_to nil, root_url %> and enter your Test ID to complete your test. Your Test ID is: <%= @candidate.test_hash %>

diff --git a/app/views/layouts/admin.html.erb b/app/views/layouts/admin.html.erb index 0beec5b..ed03bd7 100644 --- a/app/views/layouts/admin.html.erb +++ b/app/views/layouts/admin.html.erb @@ -30,7 +30,10 @@ - <%= yield %> +
"> + <%= render partial: "shared/generic_flash" %> + <%= yield %> +
diff --git a/app/views/shared/_generic_flash.html.erb b/app/views/shared/_generic_flash.html.erb new file mode 100644 index 0000000..bd703c4 --- /dev/null +++ b/app/views/shared/_generic_flash.html.erb @@ -0,0 +1,15 @@ +<% if flash[:error].present? %> +
<%= flash[:error] %>
+<% end %> + +<% if flash[:success].present? %> +
<%= flash[:success] %>
+<% end %> + +<% if flash[:warning].present? %> +
<%= flash[:warning] %>
+<% end %> + +<% if flash[:notice].present? %> +
<%= flash[:notice] %>
+<% end %> diff --git a/app/views/styleguide.html.erb b/app/views/styleguide.html.erb index eaa69e6..5594fe8 100644 --- a/app/views/styleguide.html.erb +++ b/app/views/styleguide.html.erb @@ -150,7 +150,9 @@
This is a sample error message.
- +
This is a sample success message.
+
This is a sample warning message.
+
This is a sample notice message.

diff --git a/app/views/user_mailer/password_reset.html.inky b/app/views/user_mailer/password_reset.html.inky new file mode 100644 index 0000000..38b913c --- /dev/null +++ b/app/views/user_mailer/password_reset.html.inky @@ -0,0 +1,13 @@ + + +

Hey there <%= @user.name %>,

+

+ It looks like you want to reset your password? + If not, it is safe to ignore this email. + Otherwise go to the following link to enter a new password. +

+

+ <%= link_to nil, admin_reset_url(reset_token: @user.reset_token) %>. +

+
+
diff --git a/app/views/user_mailer/password_reset.text.erb b/app/views/user_mailer/password_reset.text.erb new file mode 100644 index 0000000..5eacf4b --- /dev/null +++ b/app/views/user_mailer/password_reset.text.erb @@ -0,0 +1,7 @@ +Hey there <%= @user.name %>, + +It looks like you want to reset your password? +If not, it is safe to ignore this email. +Otherwise go to the following link to enter a new password: + +<%= admin_reset_url(reset_token: @user.reset_token) %> diff --git a/app/views/user_mailer/welcome.html.inky b/app/views/user_mailer/welcome.html.inky new file mode 100644 index 0000000..a9f7e31 --- /dev/null +++ b/app/views/user_mailer/welcome.html.inky @@ -0,0 +1,15 @@ + + +

Hey there <%= @user.name %>,

+

+ Looks like you now have access to the skills assessment app. + We've given you a temporary password below. Please sign in an personalize it asap. +

+

+ Password: <%= @password%> +

+

+ <%= link_to nil, admin_url %>. +

+
+
diff --git a/app/views/user_mailer/welcome.text.erb b/app/views/user_mailer/welcome.text.erb new file mode 100644 index 0000000..7743f45 --- /dev/null +++ b/app/views/user_mailer/welcome.text.erb @@ -0,0 +1,8 @@ +Hey there <%= @user.name %>, + +Looks like you now have access to the skills assessment app. +We've given you a temporary password below. Please sign in an personalize it asap. + +Password: <%= @password %> + +<%= admin_url %>. diff --git a/config/routes.rb b/config/routes.rb index c78aa34..3383a54 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,9 +1,11 @@ Rails.application.routes.draw do - post "/admin/login", to: "admin/auth#auth", as: :admin_auth - get "/admin/login", to: "admin/auth#login", as: :admin_login - get "/admin/logout", to: "admin/auth#logout", as: :admin_logout - - get "/admin", to: "admin#dashboard", as: :admin + post "/admin/login", to: "admin/auth#auth", as: :admin_auth + get "/admin/login", to: "admin/auth#login", as: :admin_login + get "/admin/logout", to: "admin/auth#logout", as: :admin_logout + get "/admin/reset/:reset_token", to: "admin/auth#reset", as: :admin_reset + post "/admin/reset", to: "admin/auth#reset_password", as: :admin_reset_password + get "/admin/reset_request", to: "admin/auth#reset_request", as: :admin_reset_request + post "/admin/reset_request", to: "admin/auth#send_reset", as: :admin_send_reset get "/admin/quizzes", to: "admin/quiz#index", as: :admin_quizzes get "/admin/quiz/new", to: "admin/quiz#new", as: :admin_new_quiz @@ -30,6 +32,12 @@ Rails.application.routes.draw do post "/admin/question/:question_id/edit", to: "admin/question#update", as: :admin_update_question patch "/admin/question/:question_id/edit", to: "admin/question#update" + get "/admin/profile", to: "admin/profile#view", as: :admin_profile + post "/admin/profile", to: "admin/profile#update", as: :admin_update_profile + get "/admin/profile/edit", to: "admin/profile#edit", as: :admin_edit_profile + + get "/admin", to: "admin#dashboard", as: :admin + ######################################################################################### post "/validate", to: "candidate#validate", as: :validate_candidate diff --git a/db/migrate/20160824183159_add_resets_to_users.rb b/db/migrate/20160824183159_add_resets_to_users.rb new file mode 100644 index 0000000..da9f93b --- /dev/null +++ b/db/migrate/20160824183159_add_resets_to_users.rb @@ -0,0 +1,8 @@ +class AddResetsToUsers < ActiveRecord::Migration[5.0] + def change + add_column :users, :reset_token, :string + add_column :users, :reset_timestamp, :datetime + + add_index :users, :reset_token + end +end diff --git a/db/schema.rb b/db/schema.rb index 2085033..2964332 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20160818225721) do +ActiveRecord::Schema.define(version: 20160824183159) do create_table "answers", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t| t.integer "candidate_id" @@ -73,6 +73,9 @@ ActiveRecord::Schema.define(version: 20160818225721) do t.boolean "active" t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.string "reset_token" + t.datetime "reset_timestamp" + t.index ["reset_token"], name: "index_users_on_reset_token", using: :btree end end diff --git a/test/controllers/admin/auth_controller_test.rb b/test/controllers/admin/auth_controller_test.rb index 1c22fce..f83e7ff 100644 --- a/test/controllers/admin/auth_controller_test.rb +++ b/test/controllers/admin/auth_controller_test.rb @@ -36,5 +36,54 @@ module Admin assert_redirected_to admin_login_url assert_match(/incorrect.*email/, flash[:error]) end + + test "should get reset_request" do + get admin_reset_request_url + assert_response :success + end + + test "should process a reset request" do + user = users(:admin) + assert_difference("ActionMailer::Base.deliveries.size", 1) do + post admin_send_reset_url, params: { auth: { email: user.email } } + end + refute_equal user.reset_token, User.find(user.id).reset_token + assert_redirected_to admin_reset_request_url + assert_match(/request.*sent/i, flash[:success]) + end + + test "should redirect with invalid reset_token" do + get admin_reset_url('fooBarBaz') + assert_redirected_to admin_reset_request_url + end + + test "should get reset form" do + user = users(:admin) + user.setup_reset + get admin_reset_url(user.reset_token) + assert :success + end + + test "should post password reset" do + user = users(:admin) + user.setup_reset + + post admin_reset_password_url, params: { auth: + { reset_token: user.reset_token, password: '12345', password_confirmation: '12345' } } + + assert_redirected_to admin_auth_path + assert_match(/reset.*log/i, flash[:success]) + end + + test "should fail to reset with mistyped password" do + user = users(:admin) + user.setup_reset + + post admin_reset_password_url, params: { auth: + { reset_token: user.reset_token, password: '12345', password_confirmation: 'abcde' } } + + assert :success + assert flash[:error] + end end end diff --git a/test/controllers/admin/profile_controller_test.rb b/test/controllers/admin/profile_controller_test.rb new file mode 100644 index 0000000..7f11332 --- /dev/null +++ b/test/controllers/admin/profile_controller_test.rb @@ -0,0 +1,32 @@ +require 'test_helper' + +module Admin + class ProfileControllerTest < ActionDispatch::IntegrationTest + def setup + post admin_auth_url, params: { auth: + { email: 'alan.admin@mailinator.com', password: 'password' } } + end + + test "should get view" do + get admin_profile_url + assert_response :success + end + + test "should get edit" do + get admin_edit_profile_url + assert_response :success + end + + test "should post update" do + post admin_profile_url, params: { user: { name: 'bobby tables' } } + assert_redirected_to admin_profile_url + assert flash[:success] + end + + test "should FAIL update" do + post admin_profile_url, params: { user: { name: '' } } + assert :success + assert flash[:error] + end + end +end diff --git a/test/controllers/admin/user_controller_test.rb b/test/controllers/admin/user_controller_test.rb index 8416cc8..6f0a311 100644 --- a/test/controllers/admin/user_controller_test.rb +++ b/test/controllers/admin/user_controller_test.rb @@ -28,9 +28,11 @@ module Admin end test "should post create" do - assert_difference("User.count", 1) do - post admin_create_user_url, params: { user: - { email: 'new.user@mailinator.com', name: 'New User', role: 'reviewer' } } + assert_difference("ActionMailer::Base.deliveries.size", 1) do + assert_difference("User.count", 1) do + post admin_create_user_url, params: { user: + { email: 'new.user@mailinator.com', name: 'New User', role: 'reviewer' } } + end end assert_redirected_to admin_users_url end diff --git a/test/controllers/recruiter_controller_test.rb b/test/controllers/recruiter_controller_test.rb index d63c300..41343cc 100644 --- a/test/controllers/recruiter_controller_test.rb +++ b/test/controllers/recruiter_controller_test.rb @@ -74,7 +74,7 @@ class RecruiterControllerTest < ActionDispatch::IntegrationTest end end assert_redirected_to recruiter_path - assert flash[:notice] + assert flash[:success] end test "should fail creation with message" do diff --git a/test/mailers/previews/user_mailer_preview.rb b/test/mailers/previews/user_mailer_preview.rb new file mode 100644 index 0000000..b303156 --- /dev/null +++ b/test/mailers/previews/user_mailer_preview.rb @@ -0,0 +1,12 @@ +# Preview all emails at http://localhost:3000/rails/mailers/user_mailer +class UserMailerPreview < ActionMailer::Preview + def password_reset + user = User.find_by(email: 'alan.admin@mailinator.com') + UserMailer.password_reset user + end + + def welcome + user = User.find_by(email: 'alan.admin@mailinator.com') + UserMailer.welcome user, '[default-password]' + end +end diff --git a/test/mailers/user_mailer_test.rb b/test/mailers/user_mailer_test.rb new file mode 100644 index 0000000..de58eb7 --- /dev/null +++ b/test/mailers/user_mailer_test.rb @@ -0,0 +1,20 @@ +require 'test_helper' + +class UserMailerTest < ActionMailer::TestCase + test "password_reset" do + user = users(:admin) + user.setup_reset + mail = UserMailer.password_reset user + + assert_equal [user.email], mail.to + assert_match user.reset_token, mail.body.encoded + end + + test "welcome" do + user = users(:admin) + mail = UserMailer.welcome user, 'p0o9i8u7' + + assert_equal [user.email], mail.to + assert_match 'p0o9i8u7', mail.body.encoded + end +end