diff --git a/.nvmrc b/.nvmrc
new file mode 100644
index 00000000..4a9c19cb
--- /dev/null
+++ b/.nvmrc
@@ -0,0 +1 @@
+v14.21.3
diff --git a/.tool-versions b/.tool-versions
new file mode 100644
index 00000000..974865fc
--- /dev/null
+++ b/.tool-versions
@@ -0,0 +1 @@
+ruby 2.7.6
diff --git a/Gemfile b/Gemfile
index d3e03f52..dadd465e 100644
--- a/Gemfile
+++ b/Gemfile
@@ -19,6 +19,7 @@ gem 'friendly_id', '~> 5.3.0' # 5.4.0 has a breaking change! https://github.com/
gem 'geocoder'
gem 'groupdate'
gem 'image_processing'
+gem 'invisible_captcha', '~> 2.1'
gem 'mailgun-ruby'
gem 'mini_magick'
gem 'omniauth-fablabs', github: 'academany/omniauth-fablabs'
diff --git a/Gemfile.lock b/Gemfile.lock
index 0248a422..c7be7fae 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -218,6 +218,8 @@ GEM
has_scope (~> 0.6)
railties (>= 5.2, < 6.2)
responders (>= 2, < 4)
+ invisible_captcha (2.1.0)
+ rails (>= 5.2)
jbuilder (2.10.0)
activesupport (>= 5.0.0)
jmespath (1.6.1)
@@ -470,6 +472,7 @@ DEPENDENCIES
guard-minitest
i18n-tasks
image_processing
+ invisible_captcha (~> 2.1)
jbuilder (~> 2.7)
listen (>= 3.0.5, < 3.2)
mailgun-ruby
diff --git a/README.md b/README.md
index 26d5fdee..5d65b254 100644
--- a/README.md
+++ b/README.md
@@ -11,6 +11,26 @@ Staging web server:
- http://staging.make.works/
- https://staging-makeworks.herokuapp.com/
+### Getting started locally
+- Install Ruby 2.7.6 with your version manager of choice:
+ `asdf install ruby 2.7.6; asdf local ruby 2.7.6` for asdf
+- Install bundled gems:
+ `bundle install`
+- Setup the database:
+ `bundle exec rake db:create && bundle exec rake db:schema:load`
+- Install Node 14.21.2:
+ `nvm install 14.21.2; nvm use 14.21.2` for nvm
+- Install Yarn dependencies:
+ `yarn install --check-files`
+- Ensure ActionText is installed:
+ `bundle exec rails action_text install`
+- Install chromedriver for system tests:
+ `brew install chromedriver` for homebrew on Mac OS X
+- Run tests and check they pass:
+ `bundle exec rails test && bundle exec rails test:system`
+- Run the development server:
+ `bundle exec rails server`
+
### Development
* Run tests with `rails test`
diff --git a/app/controllers/users/registrations_controller.rb b/app/controllers/users/registrations_controller.rb
new file mode 100644
index 00000000..dcf786f1
--- /dev/null
+++ b/app/controllers/users/registrations_controller.rb
@@ -0,0 +1,3 @@
+class Users::RegistrationsController < Devise::RegistrationsController
+ invisible_captcha only: [:create]
+end
\ No newline at end of file
diff --git a/app/models/user.rb b/app/models/user.rb
index eafa6aaf..74512321 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -2,7 +2,7 @@ class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
- :invitable,
+ :invitable, :confirmable,
:recoverable, :rememberable, :validatable,
:trackable,
:omniauthable,
diff --git a/app/views/devise/registrations/new.html.erb b/app/views/devise/registrations/new.html.erb
index f39fcfb4..b66d3370 100644
--- a/app/views/devise/registrations/new.html.erb
+++ b/app/views/devise/registrations/new.html.erb
@@ -12,7 +12,7 @@
<%= simple_form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
<%= f.error_notification %>
-
+ <%= invisible_captcha %>
<%= f.input :email,
required: true,
diff --git a/app/views/devise/shared/_links.html.erb b/app/views/devise/shared/_links.html.erb
index 201d6e79..210a9638 100644
--- a/app/views/devise/shared/_links.html.erb
+++ b/app/views/devise/shared/_links.html.erb
@@ -19,9 +19,13 @@
<% end %>
<%- if devise_mapping.confirmable? && controller_name != 'confirmations' %>
- <%= link_to "Didn't receive confirmation instructions?", new_confirmation_path(resource_name), class: 'text-danger my-3' %>
+
+ <%= link_to "Didn't receive confirmation instructions?", new_user_confirmation_path(resource_name), class: 'text-danger my-3' %>
+
<% end %>
<%- if devise_mapping.lockable? && resource_class.unlock_strategy_enabled?(:email) && controller_name != 'unlocks' %>
+
<%= link_to "Didn't receive unlock instructions?", new_unlock_path(resource_name), class: 'btn btn-outline-dark my-3' %>
+
<% end %>
diff --git a/config/environments/test.rb b/config/environments/test.rb
index 93ed4f1b..6dd14aa9 100644
--- a/config/environments/test.rb
+++ b/config/environments/test.rb
@@ -7,6 +7,7 @@
Rails.application.configure do
# Settings specified here will take precedence over those in config/application.rb.
+ config.assets.compile = true
config.cache_classes = false
config.action_view.cache_template_loading = true
@@ -57,4 +58,6 @@
# Annotate rendered view with file names.
# config.action_view.annotate_rendered_view_with_filenames = true
+
+ Rails.application.routes.default_url_options[:host]= 'localhost:50500'
end
diff --git a/config/routes.rb b/config/routes.rb
index 77631708..d4498f09 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -3,7 +3,8 @@
ActiveAdmin.routes(self)
devise_for :users, controllers: {
- omniauth_callbacks: 'omniauth_callbacks'
+ omniauth_callbacks: 'omniauth_callbacks',
+ registrations: 'users/registrations'
}
# Redirect rules to help the old web to new web migration
diff --git a/db/migrate/20231201122728_add_confirmable_to_devise.rb b/db/migrate/20231201122728_add_confirmable_to_devise.rb
new file mode 100644
index 00000000..be7647f6
--- /dev/null
+++ b/db/migrate/20231201122728_add_confirmable_to_devise.rb
@@ -0,0 +1,9 @@
+class AddConfirmableToDevise < ActiveRecord::Migration[6.1]
+ def change
+ add_column :users, :confirmation_token, :string
+ add_column :users, :confirmed_at, :datetime
+ add_column :users, :confirmation_sent_at, :datetime
+ add_column :users, :unconfirmed_email, :string
+ execute "UPDATE users SET confirmed_at = NOW()"
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 8bc4db54..b61a859d 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: 2021_08_23_135033) do
+ActiveRecord::Schema.define(version: 2023_12_01_122728) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@@ -429,6 +429,10 @@
t.string "invited_by_type"
t.bigint "invited_by_id"
t.integer "invitations_count", default: 0
+ t.string "confirmation_token"
+ t.datetime "confirmed_at"
+ t.datetime "confirmation_sent_at"
+ t.string "unconfirmed_email"
t.index ["invitation_token"], name: "index_users_on_invitation_token", unique: true
t.index ["invitations_count"], name: "index_users_on_invitations_count"
t.index ["invited_by_id"], name: "index_users_on_invited_by_id"
diff --git a/package.json b/package.json
index 863b8bb0..74479c8d 100644
--- a/package.json
+++ b/package.json
@@ -20,6 +20,6 @@
"webpack-dev-server": "^3.11.2"
},
"engines" : {
- "node": "14.21.2"
+ "node": "14.21.3"
}
}
diff --git a/test/controllers/users_controller_test.rb b/test/controllers/users_controller_test.rb
index dbb5d76b..30c5f3c1 100644
--- a/test/controllers/users_controller_test.rb
+++ b/test/controllers/users_controller_test.rb
@@ -40,8 +40,7 @@ class UsersControllerTest < ActionDispatch::IntegrationTest
test "should update user" do
patch user_url(@user), params: { user: { email: @user.email, first_name: @user.first_name, is_admin: @user.is_admin, last_name: @user.last_name, m_id: @user.m_id } }
- assert_response :success
- #assert_redirected_to user_url(@user)
+ assert_redirected_to user_url(@user)
end
test "should destroy user" do
diff --git a/test/fixtures/users.yml b/test/fixtures/users.yml
index 32cec5a2..d32fec0d 100644
--- a/test/fixtures/users.yml
+++ b/test/fixtures/users.yml
@@ -3,9 +3,10 @@
one:
m_id: MyString
email: admin@admin.com
- first_name: Admin
+ first_name: Administrator
last_name: Adminson
is_admin: true
+ confirmed_at: 2023-12-01T14:00:00Z
two:
m_id: MyString
@@ -13,3 +14,4 @@ two:
first_name: normal
last_name: normalson
is_admin: false
+ confirmed_at: 2023-12-01T14:00:00Z
diff --git a/test/system/login_test.rb b/test/system/login_test.rb
new file mode 100644
index 00000000..ad8dfb3f
--- /dev/null
+++ b/test/system/login_test.rb
@@ -0,0 +1,40 @@
+require "application_system_test_case"
+
+class SignUpTest < ApplicationSystemTestCase
+ setup do
+ @user = users(:one)
+ @user.password = "password123"
+ @user.password_confirmation = "password123"
+ @user.save!
+ logout
+ end
+
+ test "Confirmed user logs in" do
+ visit new_user_session_url
+
+ fill_in "Email", with: @user.email
+ fill_in "Password", with: "password123"
+
+ within "#new_user" do
+ click_on "Log in"
+ end
+
+ assert_text "Signed in successfully."
+ end
+
+ test "Unconfirmed user logs in" do
+ @user.confirmed_at = nil
+ @user.save!
+
+ visit new_user_session_url
+
+ fill_in "Email", with: @user.email
+ fill_in "Password", with: "password123"
+
+ within "#new_user" do
+ click_on "Log in"
+ end
+
+ assert_text "You have to confirm your email address before continuing."
+ end
+end
\ No newline at end of file
diff --git a/test/system/sign_up_test.rb b/test/system/sign_up_test.rb
new file mode 100644
index 00000000..6b68178d
--- /dev/null
+++ b/test/system/sign_up_test.rb
@@ -0,0 +1,20 @@
+require "application_system_test_case"
+
+class SignUpTest < ApplicationSystemTestCase
+ test "Signing up" do
+ logout
+ visit new_user_registration_url
+
+ fill_in "Email", with: "user@example.com"
+ fill_in "Password", with: "password123", match: :prefer_exact
+ fill_in "Password confirmation", with: "password123"
+ sleep 4 # The invisible_captcha bot protection will kick in if this is too quick
+ click_on "Get Started"
+
+ user = User.last
+ assert_equal user.email, "user@example.com"
+
+ visit user_confirmation_url(confirmation_token: user.confirmation_token)
+ assert_text "Your email address has been successfully confirmed."
+ end
+end
\ No newline at end of file