diff --git a/.env.sample b/.env.sample index 52515fa..75889e4 100644 --- a/.env.sample +++ b/.env.sample @@ -12,3 +12,5 @@ SENTRY_DSN= CORS_ORIGINS= MIN_COMPATIBLE_APP_VERSION= FORCE_SSL= +AUTH_API_URL= +AUTH_API_APPLICATION_ID= diff --git a/Gemfile b/Gemfile index 50899e7..0651bfe 100644 --- a/Gemfile +++ b/Gemfile @@ -46,6 +46,8 @@ gem 'newrelic_rpm' gem 'rack-cors', require: 'rack/cors' +gem 'rest-client' + group :development, :production do gem 'rails_12factor' end diff --git a/Gemfile.lock b/Gemfile.lock index 737c2c0..8a0cd5e 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -329,6 +329,7 @@ DEPENDENCIES rails (= 4.2.4) rails-api rails_12factor + rest-client rspec-rails rspec-sidekiq sentry-raven diff --git a/app/mailers/application_mailer.rb b/app/mailers/application_mailer.rb new file mode 100644 index 0000000..cf4d546 --- /dev/null +++ b/app/mailers/application_mailer.rb @@ -0,0 +1,4 @@ +class ApplicationMailer < ActionMailer::Base + default from: "support@fieldthebern.com" + layout 'mailer' +end diff --git a/app/mailers/gatekeeper_mailer.rb b/app/mailers/gatekeeper_mailer.rb new file mode 100644 index 0000000..09e61ef --- /dev/null +++ b/app/mailers/gatekeeper_mailer.rb @@ -0,0 +1,8 @@ +class GatekeeperMailer < ApplicationMailer + def pre_transfer(user) + mail( + to: user.email, + subject: "Coming soon: New user login system for Field the Bern" + ) + end +end diff --git a/app/models/api_user.rb b/app/models/api_user.rb new file mode 100644 index 0000000..453b884 --- /dev/null +++ b/app/models/api_user.rb @@ -0,0 +1,29 @@ +class ApiUser < ActiveRecord::Base + belongs_to :user + + def api_create!(user) + user_info = { + "user" => { + "email" => user.email, + "encrypted_password" => user.encrypted_password, + "first_name" => user.first_name, + "last_name" => user.last_name + } + } + + response = RestClient.post("#{ENV["AUTH_API_URL"]}/users", user_info.merge(application_id: ENV['AUTH_API_APPLICATION_ID'])) + response = JSON.load(response.body) + + ApiUser.create!(api_user_id: response["id"], api_access_token: response["access_token"], user_id: user.id) + end + + def api_save!(user_params) + user_params = ActionController::Parameters.new({ user: user_params }) + + user_info = { + "user" => user_params.require(:user).permit(:email, :encrypted_password, :first_name, :last_name).to_h + } + + RestClient.put("#{ENV["AUTH_API_URL"]}/users/me", user_info, access_token: self.api_access_token) + end +end diff --git a/app/models/user.rb b/app/models/user.rb index 5a98c32..d296911 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -3,6 +3,8 @@ class User < ActiveRecord::Base include Clearance::User + has_one :api_user + has_many :devices has_many :visits diff --git a/app/views/gatekeeper_mailer/pre_transfer.html.erb b/app/views/gatekeeper_mailer/pre_transfer.html.erb new file mode 100644 index 0000000..5a2abf9 --- /dev/null +++ b/app/views/gatekeeper_mailer/pre_transfer.html.erb @@ -0,0 +1,13 @@ +

Coming soon: New login system for Bernie 2016

+ +

+Hello! Thank you so much for helping to canvass across the United States with the Field the Bern + app! Your work is key to winning this campaign. In order to make your work easier, a new service is + being created, and it's called Gatekeeper. Gatekeeper is a single sign on (a.k.a. SSO for the techies + out there). Starting with the Field the Bern, Gatekeeper will allow volunteers to use a single email +and password across all Bernie 2016 applications. Stay tuned for more applications that will be using + this new and exciting service! + +Thanks so much for your work, +The “Field the Bern” team +

diff --git a/app/views/gatekeeper_mailer/pre_transfer.text.erb b/app/views/gatekeeper_mailer/pre_transfer.text.erb new file mode 100644 index 0000000..46f901e --- /dev/null +++ b/app/views/gatekeeper_mailer/pre_transfer.text.erb @@ -0,0 +1,11 @@ +Coming soon: New login system for Bernie 2016 + +Hello! Thank you so much for helping to canvass across the United States with the Field the Bern + app! Your work is key to winning this campaign. In order to make your work easier, a new service is + being created, and it's called Gatekeeper. Gatekeeper is a single sign on (a.k.a. SSO for the techies + out there). Starting with the Field the Bern, Gatekeeper will allow volunteers to use a single email +and password across all Bernie 2016 applications. Stay tuned for more applications that will be using + this new and exciting service! + +Thanks so much for your work, +The “Field the Bern” team diff --git a/app/views/layouts/mailer.html.erb b/app/views/layouts/mailer.html.erb new file mode 100644 index 0000000..991cf0f --- /dev/null +++ b/app/views/layouts/mailer.html.erb @@ -0,0 +1,5 @@ + + + <%= yield %> + + diff --git a/app/views/layouts/mailer.text.erb b/app/views/layouts/mailer.text.erb new file mode 100644 index 0000000..37f0bdd --- /dev/null +++ b/app/views/layouts/mailer.text.erb @@ -0,0 +1 @@ +<%= yield %> diff --git a/db/migrate/20160220020210_create_api_users.rb b/db/migrate/20160220020210_create_api_users.rb new file mode 100644 index 0000000..e6c0b3e --- /dev/null +++ b/db/migrate/20160220020210_create_api_users.rb @@ -0,0 +1,10 @@ +class CreateApiUsers < ActiveRecord::Migration + def change + create_table :api_users do |t| + t.string :api_access_token + t.integer :api_user_id + t.integer :user_id + t.timestamps null: false + end + end +end diff --git a/db/schema.rb b/db/schema.rb index ba7e9e9..30f2191 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20151220213249) do +ActiveRecord::Schema.define(version: 20160220020210) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -64,6 +64,14 @@ t.integer "last_visited_by_id" end + create_table "api_users", force: :cascade do |t| + t.string "api_access_token" + t.integer "api_user_id" + t.integer "user_id" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + create_table "devices", force: :cascade do |t| t.integer "user_id" t.string "token", null: false diff --git a/lib/tasks/gatekeeper.rake b/lib/tasks/gatekeeper.rake new file mode 100644 index 0000000..d8a95b7 --- /dev/null +++ b/lib/tasks/gatekeeper.rake @@ -0,0 +1,29 @@ +namespace :gatekeeper do + task migrate_users: :environment do + users = User.all + counter = 0 + puts "Creating API integration for #{users.count} users" + + users.each do |user| + user.api_user = ApiUser.new.api_create!(user) + counter += 1 + puts "Finished API integration for #{counter}/#{users.count}" + end + + puts "API integration completed!" + end + + task notify_users: :environment do + users = User.all + counter = 0 + puts "Sending notification mailers for #{users.count} users" + + users.each do |user| + GatekeeperMailer.pre_transfer(user) + counter += 1 + puts "Sent notification mailer for #{counter}/#{users.count}" + end + + puts "Notification mailer email blast completed!" + end +end diff --git a/spec/mailers/gatekeeper_mailer_spec.rb b/spec/mailers/gatekeeper_mailer_spec.rb new file mode 100644 index 0000000..193ee2c --- /dev/null +++ b/spec/mailers/gatekeeper_mailer_spec.rb @@ -0,0 +1,20 @@ +require "rails_helper" + +RSpec.describe GatekeeperMailer, type: :mailer do + describe "pre_transfer" do + before do + @user = FactoryGirl.create(:user) + @mail = GatekeeperMailer.pre_transfer(@user) + end + + it "renders the headers" do + expect(@mail.subject).to eq("Coming soon: New user login system for Field the Bern") + expect(@mail.to).to eq([@user.email]) + expect(@mail.from).to eq(["team@fieldthebern.com"]) + end + + it "renders the body" do + expect(@mail.body.encoded).to match("Coming soon") + end + end +end diff --git a/spec/models/api_user_spec.rb b/spec/models/api_user_spec.rb new file mode 100644 index 0000000..c390337 --- /dev/null +++ b/spec/models/api_user_spec.rb @@ -0,0 +1,13 @@ +require 'rails_helper' + +RSpec.describe ApiUser, type: :model do + context 'schema' do + it { should have_db_column(:api_access_token).of_type(:string) } + it { should have_db_column(:api_user_id).of_type(:integer) } + it { should have_db_column(:user_id).of_type(:integer) } + end + + context 'associations' do + it { should belong_to(:user) } + end +end diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index a342be2..5586f2d 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -32,6 +32,7 @@ it { should have_many(:passive_relationships) } it { should have_many(:followers) } it { should have_many(:following) } + it { should have_one(:api_user) } end context 'validations' do