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