sqlite3, test coverage improvements, auto auth
This commit is contained in:
parent
41ceccc5b5
commit
7ddf93578e
10
Gemfile
10
Gemfile
@ -1,5 +1,5 @@
|
||||
source 'https://rubygems.org'
|
||||
ruby "2.2.2"
|
||||
ruby "2.2.3"
|
||||
|
||||
gem 'figaro', '~> 1.1.1'
|
||||
gem 'bcrypt', '~> 3.1.7'
|
||||
@ -13,19 +13,13 @@ gem 'haml-rails', "~> 0.9"
|
||||
gem 'jquery-rails'
|
||||
gem 'json', '~> 1.8.3'
|
||||
gem 'mailjet', '~> 1.1.0'
|
||||
gem 'mysql2', '~> 0.3.20'
|
||||
gem 'responders', '~> 2.1.0'
|
||||
gem 'sass-rails', '~> 5.0'
|
||||
gem 'sorcery', '~> 0.9.1'
|
||||
gem 'sqlite3', '~> 1.3.11'
|
||||
gem 'twilio-ruby', '~> 4.3.0'
|
||||
gem 'uglifier', '>= 1.3.0'
|
||||
|
||||
# gem 'faraday'
|
||||
# gem 'faraday_middleware'
|
||||
# gem 'rack-protection', '~> 1.5.3'
|
||||
# gem 'rabl-rails', '~> 0.4.1'
|
||||
# gem 'jbuilder', '~> 2.0'
|
||||
|
||||
group :development, :test do
|
||||
gem 'awesome_print'
|
||||
gem 'binding_of_caller'
|
||||
|
48
Gemfile.lock
48
Gemfile.lock
@ -71,7 +71,7 @@ GEM
|
||||
erubis (2.7.0)
|
||||
eventmachine (1.0.8)
|
||||
execjs (2.6.0)
|
||||
faraday (0.9.1)
|
||||
faraday (0.9.2)
|
||||
multipart-post (>= 1.2, < 3)
|
||||
ffi (1.9.10)
|
||||
figaro (1.1.1)
|
||||
@ -89,9 +89,10 @@ GEM
|
||||
shellany (~> 0.0)
|
||||
thor (>= 0.18.1)
|
||||
guard-compat (1.2.1)
|
||||
guard-livereload (2.4.0)
|
||||
guard-livereload (2.5.0)
|
||||
em-websocket (~> 0.5)
|
||||
guard (~> 2.8)
|
||||
guard-compat (~> 1.0)
|
||||
multi_json (~> 1.8)
|
||||
guard-minitest (2.4.4)
|
||||
guard-compat (~> 1.2)
|
||||
@ -105,7 +106,7 @@ GEM
|
||||
guard-shell (0.7.1)
|
||||
guard (>= 2.0.0)
|
||||
guard-compat (~> 1.0)
|
||||
haml (4.0.6)
|
||||
haml (4.0.7)
|
||||
tilt
|
||||
haml-rails (0.9.0)
|
||||
actionpack (>= 4.0.1)
|
||||
@ -131,7 +132,7 @@ GEM
|
||||
railties (>= 4.2.0)
|
||||
thor (>= 0.14, < 2.0)
|
||||
json (1.8.3)
|
||||
jwt (1.4.1)
|
||||
jwt (1.5.1)
|
||||
listen (3.0.3)
|
||||
rb-fsevent (>= 0.9.3)
|
||||
rb-inotify (>= 0.9)
|
||||
@ -145,10 +146,10 @@ GEM
|
||||
rack (>= 1.4.0)
|
||||
rest-client
|
||||
method_source (0.8.2)
|
||||
mime-types (2.6.1)
|
||||
mime-types (2.6.2)
|
||||
mini_portile (0.6.2)
|
||||
minitest (5.8.0)
|
||||
minitest-reporters (1.0.16)
|
||||
minitest (5.8.1)
|
||||
minitest-reporters (1.1.4)
|
||||
ansi
|
||||
builder
|
||||
minitest (>= 5.0)
|
||||
@ -156,12 +157,11 @@ GEM
|
||||
multi_json (1.11.2)
|
||||
multi_xml (0.5.5)
|
||||
multipart-post (2.0.0)
|
||||
mysql2 (0.3.20)
|
||||
nenv (0.2.0)
|
||||
netrc (0.10.3)
|
||||
nokogiri (1.6.6.2)
|
||||
mini_portile (~> 0.6.0)
|
||||
notiffany (0.0.7)
|
||||
notiffany (0.0.8)
|
||||
nenv (~> 0.1)
|
||||
shellany (~> 0.0)
|
||||
oauth (0.4.7)
|
||||
@ -171,10 +171,10 @@ GEM
|
||||
multi_json (~> 1.3)
|
||||
multi_xml (~> 0.5)
|
||||
rack (~> 1.2)
|
||||
parser (2.2.2.6)
|
||||
parser (2.2.3.0)
|
||||
ast (>= 1.1, < 3.0)
|
||||
powerpack (0.1.1)
|
||||
pry (0.10.1)
|
||||
pry (0.10.3)
|
||||
coderay (~> 1.1.0)
|
||||
method_source (~> 0.8.1)
|
||||
slop (~> 3.4)
|
||||
@ -214,7 +214,7 @@ GEM
|
||||
thor (>= 0.18.1, < 2.0)
|
||||
rainbow (2.0.0)
|
||||
rake (10.4.2)
|
||||
rb-fsevent (0.9.5)
|
||||
rb-fsevent (0.9.6)
|
||||
rb-inotify (0.9.5)
|
||||
ffi (>= 0.5.0)
|
||||
responders (2.1.0)
|
||||
@ -223,16 +223,16 @@ GEM
|
||||
http-cookie (>= 1.0.2, < 2.0)
|
||||
mime-types (>= 1.16, < 3.0)
|
||||
netrc (~> 0.7)
|
||||
rubocop (0.33.0)
|
||||
rubocop (0.34.2)
|
||||
astrolabe (~> 1.3)
|
||||
parser (>= 2.2.2.5, < 3.0)
|
||||
powerpack (~> 0.1)
|
||||
rainbow (>= 1.99.1, < 3.0)
|
||||
ruby-progressbar (~> 1.4)
|
||||
ruby-progressbar (1.7.5)
|
||||
ruby_parser (3.6.6)
|
||||
ruby_parser (3.7.1)
|
||||
sexp_processor (~> 4.1)
|
||||
sass (3.4.18)
|
||||
sass (3.4.19)
|
||||
sass-rails (5.0.4)
|
||||
railties (>= 4.0.0, < 5.0)
|
||||
sass (~> 3.1)
|
||||
@ -242,24 +242,25 @@ GEM
|
||||
scss-lint (0.30.0)
|
||||
rainbow (~> 2.0)
|
||||
sass (~> 3.4.0)
|
||||
sexp_processor (4.5.1)
|
||||
sexp_processor (4.6.0)
|
||||
shellany (0.0.1)
|
||||
slop (3.6.0)
|
||||
sorcery (0.9.1)
|
||||
bcrypt (~> 3.1)
|
||||
oauth (~> 0.4, >= 0.4.4)
|
||||
oauth2 (>= 0.8.0)
|
||||
spring (1.3.6)
|
||||
sprockets (3.3.4)
|
||||
rack (~> 1.0)
|
||||
spring (1.4.0)
|
||||
sprockets (3.4.0)
|
||||
rack (> 1, < 3)
|
||||
sprockets-rails (2.3.3)
|
||||
actionpack (>= 3.0)
|
||||
activesupport (>= 3.0)
|
||||
sprockets (>= 2.8, < 4.0)
|
||||
sqlite3 (1.3.11)
|
||||
sysexits (1.2.0)
|
||||
thin (1.6.3)
|
||||
thin (1.6.4)
|
||||
daemons (~> 1.0, >= 1.0.9)
|
||||
eventmachine (~> 1.0)
|
||||
eventmachine (~> 1.0, >= 1.0.4)
|
||||
rack (~> 1.0)
|
||||
thor (0.19.1)
|
||||
thread_safe (0.3.5)
|
||||
@ -306,7 +307,6 @@ DEPENDENCIES
|
||||
json (~> 1.8.3)
|
||||
mailjet (~> 1.1.0)
|
||||
minitest-reporters
|
||||
mysql2 (~> 0.3.20)
|
||||
pry-byebug
|
||||
pry-rails
|
||||
rack-livereload
|
||||
@ -316,8 +316,12 @@ DEPENDENCIES
|
||||
sass-rails (~> 5.0)
|
||||
sorcery (~> 0.9.1)
|
||||
spring
|
||||
sqlite3 (~> 1.3.11)
|
||||
thin (~> 1.6.3)
|
||||
turbolinks
|
||||
twilio-ruby (~> 4.3.0)
|
||||
uglifier (>= 1.3.0)
|
||||
web-console (~> 2.0)
|
||||
|
||||
BUNDLED WITH
|
||||
1.10.6
|
||||
|
@ -6,16 +6,15 @@ A simple app to send sms messages with [twillio](https://www.twilio.com/).
|
||||
|
||||
### Secrets file:
|
||||
|
||||
`config/secrets.yml` is read at boot and shoves the values into `ENV`.
|
||||
`config/application.yml` is read at boot and shoves the values into `ENV`.
|
||||
|
||||
1. Copy `config/secrets.yml.sample` and rename to `config/secrets.yml`.
|
||||
1. Copy `config/application.yml.sample` and rename to `config/application.yml`.
|
||||
2. Edit file and set/define as many secrets as you need. The sample file has the minimum expected keys.
|
||||
3. Make *ABSOLUTE* certain that this file is not checked into your repository.
|
||||
|
||||
## TODO
|
||||
|
||||
* sorcery or a lower oauth solution
|
||||
* activation flag on user edit
|
||||
* verify roles access
|
||||
* application log
|
||||
* app version file - milestone 0.9.0
|
||||
* task runner - delayedjob or sidekiq or activerecord newness?
|
||||
* milestone 1.0.0
|
||||
|
@ -10,21 +10,44 @@ class OauthsController < ApplicationController
|
||||
@user = login_from(provider)
|
||||
|
||||
if @user
|
||||
redirect_to root_path, notice: "Logged in from #{provider.titleize}!"
|
||||
redirect_to root_path, notice: login_msg(@user, provider)
|
||||
else
|
||||
msg = "Your account must be pre-approved. Please contact the administrator."
|
||||
redirect_to root_path, notice: msg
|
||||
@user = auth_and_login(provider)
|
||||
redirect_to root_path, notice: login_msg(@user, provider)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# def create_and_login provider
|
||||
# @user = create_from(provider)
|
||||
# reset_session # protect from session fixation attack
|
||||
# auto_login(@user)
|
||||
# redirect_to root_path, notice: "Logged in from #{provider.titleize}!"
|
||||
# end
|
||||
def login_msg user, provider = 'oAuth'
|
||||
if user.active?
|
||||
"Logged in from #{provider.titleize}!"
|
||||
else
|
||||
"Your account must be activated by an administrator."
|
||||
end
|
||||
end
|
||||
|
||||
def auth_and_login provider
|
||||
user = create_auth_from(provider, auth_info)
|
||||
reset_session # protect from session fixation attack
|
||||
auto_login(user) if user.active?
|
||||
user
|
||||
end
|
||||
|
||||
def create_auth_from provider, auth
|
||||
user = Person.find_by_email auth[:user_info]["email"]
|
||||
user.authentications.create(provider: provider, uid: auth[:uid])
|
||||
user
|
||||
end
|
||||
|
||||
def auth_info
|
||||
@auth_info ||= google_hash
|
||||
end
|
||||
|
||||
def google_hash
|
||||
ga = Sorcery::Providers::Google.new
|
||||
ga.get_user_hash access_token
|
||||
end
|
||||
|
||||
def auth_params
|
||||
params.permit(:code, :provider)
|
||||
|
@ -1,3 +1,4 @@
|
||||
class Authentication < ActiveRecord::Base
|
||||
belongs_to :user
|
||||
belongs_to :person
|
||||
validates :uid, presence: true, uniqueness: { scope: :provider }
|
||||
end
|
||||
|
@ -11,7 +11,7 @@ class Person < ActiveRecord::Base
|
||||
validates :phone, presence: true
|
||||
|
||||
scope :with_name, lambda { |name|
|
||||
where("concat(first_name, ' ', last_name) RLIKE ?", name)
|
||||
where("first_name || ' ' || last_name LIKE ?", "%#{name}%")
|
||||
}
|
||||
|
||||
scope :just_parents, lambda {
|
||||
@ -34,6 +34,10 @@ class Person < ActiveRecord::Base
|
||||
id
|
||||
end
|
||||
|
||||
def active?
|
||||
activation_state == "active"
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
## SorceryCore expects the model to hold a crypted_password field
|
||||
|
@ -1,3 +1,3 @@
|
||||
%h2 Edit #{@user.name}
|
||||
|
||||
= render partial: 'form', locals: {form_action: edit_user_path}
|
||||
= render partial: 'form', locals: { form_action: edit_user_path }
|
||||
|
@ -1,3 +1,3 @@
|
||||
%h2 Register a new User
|
||||
|
||||
= render partial: 'form', locals: {form_action: add_user_path}
|
||||
= render partial: 'form', locals: { form_action: add_user_path }
|
||||
|
@ -1,22 +1,19 @@
|
||||
---
|
||||
default: &default
|
||||
adapter: mysql2
|
||||
adapter: sqlite3
|
||||
database: db/default.sqlite3
|
||||
encoding: utf8
|
||||
reconnect: false
|
||||
pool: 5
|
||||
host: localhost
|
||||
# socket: /tmp/mysql.sock
|
||||
timeout: 5000
|
||||
|
||||
development:
|
||||
<<: *default
|
||||
database: sms-pager-dev
|
||||
database: db/development.sqlite3
|
||||
|
||||
test:
|
||||
<<: *default
|
||||
database: sms-pager-test
|
||||
database: db/test.sqlite3
|
||||
|
||||
production:
|
||||
<<: *default
|
||||
database: sms-pager-api
|
||||
username: <%= ENV["mysql_usr"] %>
|
||||
password: <%= ENV["mysql_pwd"] %>
|
||||
database: db/production.sqlite3
|
||||
|
@ -131,7 +131,7 @@ Rails.application.config.sorcery.configure do |config|
|
||||
config.google.key = ENV["google_key"]
|
||||
config.google.secret = ENV["google_secret"]
|
||||
config.google.callback_url = "http://localhost:3000/oauth/callback?provider=google"
|
||||
config.google.user_info_mapping = { email: "email" }
|
||||
config.google.user_info_mapping = { email: "email", first_name: "given_name", last_name: "family_name" }
|
||||
|
||||
# config.vk.key = ""
|
||||
# config.vk.secret = ""
|
||||
|
46
db/schema.rb
46
db/schema.rb
@ -14,51 +14,51 @@
|
||||
ActiveRecord::Schema.define(version: 20151008022535) do
|
||||
|
||||
create_table "authentications", force: :cascade do |t|
|
||||
t.integer "person_id", limit: 4, null: false
|
||||
t.string "provider", limit: 255, null: false
|
||||
t.string "uid", limit: 255, null: false
|
||||
t.integer "person_id", null: false
|
||||
t.string "provider", null: false
|
||||
t.string "uid", null: false
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
end
|
||||
|
||||
add_index "authentications", ["provider", "uid"], name: "index_authentications_on_provider_and_uid", using: :btree
|
||||
add_index "authentications", ["provider", "uid"], name: "index_authentications_on_provider_and_uid"
|
||||
|
||||
create_table "children", force: :cascade do |t|
|
||||
t.string "first_name", limit: 255
|
||||
t.string "last_name", limit: 255
|
||||
t.string "first_name"
|
||||
t.string "last_name"
|
||||
end
|
||||
|
||||
create_table "pages", force: :cascade do |t|
|
||||
t.integer "user_id", limit: 4
|
||||
t.integer "person_id", limit: 4
|
||||
t.string "to", limit: 255
|
||||
t.string "message", limit: 255
|
||||
t.string "status", limit: 255
|
||||
t.integer "user_id"
|
||||
t.integer "person_id"
|
||||
t.string "to"
|
||||
t.string "message"
|
||||
t.string "status"
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
end
|
||||
|
||||
create_table "parenthoods", force: :cascade do |t|
|
||||
t.integer "person_id", limit: 4
|
||||
t.integer "child_id", limit: 4
|
||||
t.integer "person_id"
|
||||
t.integer "child_id"
|
||||
end
|
||||
|
||||
add_index "parenthoods", ["person_id", "child_id"], name: "parentship", using: :btree
|
||||
add_index "parenthoods", ["person_id", "child_id"], name: "parentship"
|
||||
|
||||
create_table "people", force: :cascade do |t|
|
||||
t.string "first_name", limit: 255
|
||||
t.string "last_name", limit: 255
|
||||
t.string "phone", limit: 255
|
||||
t.string "email", limit: 255, null: false
|
||||
t.string "first_name"
|
||||
t.string "last_name"
|
||||
t.string "phone"
|
||||
t.string "email", null: false
|
||||
t.boolean "admin"
|
||||
t.boolean "staff"
|
||||
t.string "activation_state", limit: 255
|
||||
t.string "activation_token", limit: 255
|
||||
t.string "activation_state"
|
||||
t.string "activation_token"
|
||||
t.datetime "activation_token_expires_at"
|
||||
end
|
||||
|
||||
add_index "people", ["activation_token"], name: "index_people_on_activation_token", using: :btree
|
||||
add_index "people", ["email"], name: "index_people_on_email", unique: true, using: :btree
|
||||
add_index "people", ["phone"], name: "index_people_on_phone", using: :btree
|
||||
add_index "people", ["activation_token"], name: "index_people_on_activation_token"
|
||||
add_index "people", ["email"], name: "index_people_on_email", unique: true
|
||||
add_index "people", ["phone"], name: "index_people_on_phone"
|
||||
|
||||
end
|
||||
|
7
test/fixtures/people.yml
vendored
7
test/fixtures/people.yml
vendored
@ -42,3 +42,10 @@ sarah:
|
||||
email: sarah.smith@mailinator.com
|
||||
phone: 5005550006
|
||||
children: sally, nemo
|
||||
mmoser:
|
||||
first_name: Mark
|
||||
last_name: Moser
|
||||
email: markamoser@gmail.com
|
||||
phone: 3093634474
|
||||
admin: true
|
||||
activation_state: active
|
||||
|
15
test/models/child_test.rb
Normal file
15
test/models/child_test.rb
Normal file
@ -0,0 +1,15 @@
|
||||
require 'test_helper'
|
||||
|
||||
class ChildTest < ActiveSupport::TestCase
|
||||
def test_sanity
|
||||
assert Child
|
||||
end
|
||||
|
||||
def test_relations
|
||||
non_relatives = Child.not_related_to people(:marlin)
|
||||
smiths_count = non_relatives.where(last_name: 'smith').count
|
||||
|
||||
assert_equal 0, smiths_count
|
||||
assert_equal 1, non_relatives.count
|
||||
end
|
||||
end
|
@ -10,4 +10,19 @@ class PersonTest < ActiveSupport::TestCase
|
||||
|
||||
assert parents.count > 1, "Did not find more than one parent"
|
||||
end
|
||||
|
||||
def test_name_first
|
||||
assert_equal 1, Person.with_name('admin').count
|
||||
end
|
||||
|
||||
def test_name_last
|
||||
smiths_count = Person.where(last_name: 'Smith').count
|
||||
smiths = Person.with_name 'smith'
|
||||
|
||||
assert_equal smiths_count, smiths.count
|
||||
end
|
||||
|
||||
def test_name_full
|
||||
assert_equal 1, Person.with_name('wanda worker').count
|
||||
end
|
||||
end
|
||||
|
1
version.md
Normal file
1
version.md
Normal file
@ -0,0 +1 @@
|
||||
version 0.9.0
|
Loading…
Reference in New Issue
Block a user