wcc-auth 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 6c2afec20c4229b28f32abae4da9d22644c57bb2
4
+ data.tar.gz: 84abb21d431971dd9ce00576fac0f7aa5b5411d3
5
+ SHA512:
6
+ metadata.gz: b64cd3fccbe65635e39dd47a8e162ec073c960611f2c566ce8db7da513dbdc86a18bbb04427fa14c38f2b1ef8865d30a173a343db1f8a25a19453d5ec710ef8b
7
+ data.tar.gz: 5a86a83daf93ec913e5c00bd6fbbf771cedd3357237a7c05d928521ed02c8b28afab82e277fe9d53581c167c95ab4e574e001c8757bb71bbf9274493fb0e2ff1
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format progress
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in wcc-auth.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2014 Watermark Community Church, Dallas, TX
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,115 @@
1
+ # WCC::Auth
2
+
3
+ Provides the necessary tools for handling authentication through
4
+ Watermark's OAuth provider as well as authorizing the user has access to
5
+ specific features within the application. There are special hooks for
6
+ Rails apps using Devise, but the primitive structures could be used on
7
+ any Ruby project. Currently, the only tested path is Rails with Devise.
8
+
9
+ ## Installation
10
+
11
+ Add this line to your application's Gemfile:
12
+
13
+ ```ruby
14
+ gem 'wcc-auth', '~> 0.3.0'
15
+ ```
16
+
17
+ If you are using a Rails app with Devise you can use a special require
18
+ hook that will setup all the Devise specific configuration for you.
19
+
20
+ ```ruby
21
+ gem 'wcc-auth', '~> 0.3.0', require: 'wcc/auth/devise'
22
+ ```
23
+
24
+ ## Configuration
25
+
26
+ There are a few steps to setup your app. These instructions are specific
27
+ to a Rails app.
28
+
29
+ #### Add the configuration block to an initializer
30
+
31
+ In order to configure the gem you must run the `WCC::Auth.setup` block.
32
+ See below for an example:
33
+
34
+ ```ruby
35
+ WCC::Auth.setup do |config|
36
+ config.app_name = "app-name"
37
+ config.environment = Rails.env
38
+ config.app_id = 'app-client-id-from-oauth-provider'
39
+ config.app_secret = 'app-client-secret-from-oauth-provider'
40
+ end
41
+ ```
42
+
43
+ #### Setup your controllers
44
+
45
+ ```ruby
46
+ # Add this include to your ApplicationController
47
+ class ApplicationController < ActionController::Base
48
+ include WCC::Auth::ControllerHelpers
49
+ end
50
+ ```
51
+
52
+ #### Setup your user model
53
+
54
+ ```ruby
55
+ class User < ActiveRecord::Base
56
+ include WCC::Auth::Providers::ActiveRecord
57
+
58
+ # ...
59
+
60
+ end
61
+ ```
62
+
63
+ #### Setup authorization (optional)
64
+
65
+ If you would like to use the `TieredAbility` class included with
66
+ `WCC::Auth` just create an Ability class that extends the
67
+ `WCC::Auth::TieredAbility` class. The authenticated user will include an
68
+ info variables called `access_level_id`. This corresponds to a
69
+ `WCC::Auth::AccessLevel`.
70
+
71
+ The access levels are broken down into 5 tiers with the following rules:
72
+
73
+ * **No access** -- This is the default level
74
+ * **Basic** -- This is provides read-only access
75
+ * **Contribute** -- Read-write for only data the user owns
76
+ * **Manage** -- Read-write for other's data
77
+ * **App Admin** -- Can change app configuration
78
+ * **System Admin** -- Has full access to all features always
79
+
80
+ Each tier inherits all priveleges of the lower tiers. The rules here are
81
+ guidelines for the app to follow. It is ultimately up to the client
82
+ application to decide what each of these tiers means for it. Do your
83
+ best to adhere to these rules.
84
+
85
+ Here is an example Ability class using the DSL provided by `WCC::Auth`.
86
+
87
+ ```ruby
88
+ class Ability < WCC::Auth::TieredAbility
89
+ at_level(:contribute) do |user|
90
+ can :read, Person
91
+ can :manage, Task, created_by_id: user.id
92
+ can :manage, Comment, created_by_id: user.id
93
+
94
+ cannot :destroy, Task
95
+ end
96
+
97
+ at_level(:appadmin) do |user|
98
+ can :manage, :all
99
+ cannot :create, TaskGroup
100
+ end
101
+
102
+
103
+ at_level(:sysadmin) do |user|
104
+ can :manage, :all
105
+ end
106
+ end
107
+ ```
108
+
109
+ ## Contributing
110
+
111
+ 1. Fork it
112
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
113
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
114
+ 4. Push to the branch (`git push origin my-new-feature`)
115
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ task :default => :test
4
+
5
+ desc "Run the RSpec test suite"
6
+ task :test do
7
+ exec "rspec ."
8
+ end
@@ -0,0 +1,29 @@
1
+ class OmniAuth::Strategies::Watermark < OmniAuth::Strategies::OAuth2
2
+ option :name, :watermark
3
+
4
+ option :client_options, {
5
+ site: WCC::Auth.config.authorize_site,
6
+ authorize_path: WCC::Auth.config.authorize_path,
7
+ }
8
+
9
+ option :authorize_params, WCC::Auth.config.authorize_params
10
+
11
+ uid do
12
+ raw_info["id"]
13
+ end
14
+
15
+ info do
16
+ {
17
+ email: raw_info["email"],
18
+ first_name: raw_info["first_name"],
19
+ last_name: raw_info["last_name"],
20
+ access_level_id: raw_info["access_level_id"],
21
+ arena_id: raw_info["arena_id"],
22
+ }
23
+ end
24
+
25
+ def raw_info
26
+ @raw_info ||= access_token.get('/api/v1/me.json').parsed
27
+ end
28
+
29
+ end
@@ -0,0 +1,36 @@
1
+ require 'cancan'
2
+
3
+ class WCC::Auth::TieredAbility
4
+ include CanCan::Ability
5
+
6
+ def initialize(user)
7
+ @user = user
8
+ grant_access_at(@user.access_level)
9
+ end
10
+
11
+ def grant_access_at(access_level)
12
+ levels.each do |level, can_blocks|
13
+ if access_level >= level
14
+ can_blocks.each { |can_block| instance_exec(@user, &can_block) }
15
+ end
16
+ end
17
+ end
18
+
19
+ def levels
20
+ self.class.levels
21
+ end
22
+
23
+ def self.at_level(level_key, &can_block)
24
+ level = WCC::Auth::AccessLevel[level_key] or
25
+ raise ArgumentError, "#{level_key} is not a valid access level"
26
+ levels[level] << can_block
27
+ end
28
+
29
+ def self.levels
30
+ @levels ||= Hash.new { |hash, key| hash[key] = [] }
31
+ end
32
+
33
+ def self.inherited(subclass)
34
+ subclass.send :instance_variable_set, :@levels, levels.dup
35
+ end
36
+ end
@@ -0,0 +1,38 @@
1
+ module WCC::Auth
2
+
3
+ ACCESS_LEVELS = [
4
+ { id: nil, name: "None", slug: "none", description: "no access", level: 0 },
5
+ { id: 1, name: "Basic", slug: "basic", description: "read access", level: 1 },
6
+ { id: 2, name: "Contribute", slug: "contribute", description: "read-write of data user owns", level: 2 },
7
+ { id: 3, name: "Manage", slug: "manage", description: "read-write of other's data", level: 3 },
8
+ { id: 4, name: "App Admin", slug: "appadmin", description: "read-write app configuration", level: 4 },
9
+ { id: 5, name: "System Admin", slug: "sysadmin", description: "full access", level: 5 },
10
+ ]
11
+
12
+ AccessLevel = Struct.new(:id, :name, :slug, :description, :level) do
13
+ include Comparable
14
+
15
+ def <=>(record)
16
+ self.level <=> record.level
17
+ end
18
+
19
+ def self.[](index_or_slug, db=ACCESS_LEVELS)
20
+ all(db).select do |al|
21
+ al.level.to_s === index_or_slug.to_s ||
22
+ al.slug === index_or_slug.to_s
23
+ end.last
24
+ end
25
+
26
+ def self.all(db=ACCESS_LEVELS)
27
+ db.collect do |row|
28
+ new.tap { |access_level|
29
+ row.each { |field, value|
30
+ access_level[field] = value
31
+ }
32
+ }
33
+ end.sort
34
+ end
35
+
36
+ end
37
+
38
+ end
@@ -0,0 +1,77 @@
1
+ WCC::Auth::Config = Struct.new(:environment,
2
+ :app_name,
3
+ :app_url,
4
+ :app_url_protocol,
5
+ :app_id,
6
+ :app_secret,
7
+ :app_domain_suffix,
8
+ :authorize_site,
9
+ :authorize_path,
10
+ :authorize_params) do
11
+
12
+ def authorize_site
13
+ self[:authorize_site] || default_authorize_site
14
+ end
15
+
16
+ def authorize_path
17
+ self[:authorize_path] || "/oauth/authorize"
18
+ end
19
+
20
+ def authorize_params
21
+ self[:authorize_params] || {}
22
+ end
23
+
24
+ def app_url
25
+ self[:app_url] || default_app_url
26
+ end
27
+
28
+ def app_url_protocol
29
+ self[:app_domain_suffix] || default_app_url_protocol
30
+ end
31
+
32
+ def app_domain_suffix
33
+ self[:app_domain_suffix] || default_app_domain_suffix
34
+ end
35
+
36
+ def nucleus_url
37
+ case environment.to_sym
38
+ when :production
39
+ "https://login.watermark.org"
40
+ when :staging
41
+ "http://login.staging.watermark.org"
42
+ when :development
43
+ "http://login.dev"
44
+ end
45
+ end
46
+
47
+ private
48
+
49
+ def default_app_url
50
+ "#{app_url_protocol}://#{app_name}#{app_domain_suffix}"
51
+ end
52
+
53
+ def default_app_url_protocol
54
+ case environment.to_sym
55
+ when :production
56
+ "https"
57
+ else
58
+ "http"
59
+ end
60
+ end
61
+
62
+ def default_app_domain_suffix
63
+ case environment.to_sym
64
+ when :production
65
+ ".watermark.org"
66
+ when :staging
67
+ ".staging.watermark.org"
68
+ when :development
69
+ ".dev"
70
+ end
71
+ end
72
+
73
+ def default_authorize_site
74
+ nucleus_url
75
+ end
76
+
77
+ end
@@ -0,0 +1,11 @@
1
+ module WCC::Auth::ControllerHelpers
2
+
3
+ def access_level
4
+ current_user.access_level
5
+ end
6
+
7
+ def self.included(receiver)
8
+ receiver.helper_method :access_level
9
+ end
10
+
11
+ end
@@ -0,0 +1,26 @@
1
+ class WCC::Auth::Devise::WatermarkCallbacksController < Devise::OmniauthCallbacksController
2
+ skip_authorization_check if respond_to?(:skip_authorization_check)
3
+
4
+ def watermark
5
+ oauth_data = request.env["omniauth.auth"]
6
+ @user = User.initialize_from_watermark_oauth(oauth_data)
7
+ @user.save
8
+
9
+ sign_in_and_redirect @user
10
+ end
11
+
12
+ def failure
13
+ Rails.logger.error failed_strategy.name
14
+ Rails.logger.error failure_message
15
+ set_flash_message :alert, :failure, :kind => OmniAuth::Utils.camelize(failed_strategy.name), :reason => failure_message
16
+ redirect_to after_omniauth_failure_path_for(resource_name)
17
+ end
18
+
19
+ protected
20
+
21
+ def after_omniauth_failure_path_for(scope)
22
+ root_path
23
+ end
24
+
25
+ end
26
+
@@ -0,0 +1,22 @@
1
+ require "wcc/auth"
2
+ require "devise"
3
+
4
+ module WCC
5
+ module Auth
6
+ module Devise
7
+ autoload :WatermarkCallbacksController, 'wcc/auth/devise/watermark_callbacks_controller'
8
+ end
9
+ end
10
+ end
11
+
12
+ WCC::Auth.finalize_callbacks << -> {
13
+ require "omniauth/strategies/watermark"
14
+ Devise.setup do |config|
15
+ config.omniauth :watermark,
16
+ WCC::Auth.config.app_id,
17
+ WCC::Auth.config.app_secret
18
+ end
19
+
20
+ OmniAuth.config.full_host = WCC::Auth.config.app_url
21
+ }
22
+
@@ -0,0 +1,41 @@
1
+ module WCC::Auth::Providers::ActiveRecord
2
+
3
+ module ClassMethods
4
+
5
+ def credential_data_mapping(oauth_data)
6
+ {
7
+ email: oauth_data.info.email,
8
+ first_name: oauth_data.info.first_name,
9
+ last_name: oauth_data.info.last_name,
10
+ access_token: oauth_data.credentials.token,
11
+ access_level_id: oauth_data.info.access_level_id,
12
+ }
13
+ end
14
+
15
+ def initialize_from_watermark_oauth(oauth_data)
16
+ find_or_initialize_by(provider: :watermark, uid: oauth_data.uid).tap do |user|
17
+ user.assign_attributes(credential_data_mapping(oauth_data))
18
+ end
19
+ end
20
+
21
+ end
22
+
23
+ module InstanceMethods
24
+
25
+ def access_level
26
+ WCC::Auth::AccessLevel[access_level_id || :none]
27
+ end
28
+
29
+ def has_access?(level)
30
+ access_level >= WCC::Auth::AccessLevel[level]
31
+ end
32
+
33
+ end
34
+
35
+ def self.included(receiver)
36
+ receiver.send :extend, ClassMethods
37
+ receiver.send :include, InstanceMethods
38
+ end
39
+
40
+ end
41
+
@@ -0,0 +1,8 @@
1
+ module WCC
2
+ module Auth
3
+ module Providers
4
+ end
5
+ end
6
+ end
7
+
8
+ require 'wcc/auth/providers/active_record'
@@ -0,0 +1,5 @@
1
+ module WCC
2
+ module Auth
3
+ VERSION = "0.3.0"
4
+ end
5
+ end
data/lib/wcc/auth.rb ADDED
@@ -0,0 +1,33 @@
1
+ require "wcc/auth/version"
2
+ require "wcc/auth/config"
3
+
4
+ require "wcc/auth/access_level"
5
+ require "wcc/auth/ability"
6
+ require "wcc/auth/providers"
7
+ require "wcc/auth/controller_helpers"
8
+
9
+ require "omniauth"
10
+ require "omniauth-oauth2"
11
+
12
+ module WCC
13
+ module Auth
14
+
15
+ def self.setup
16
+ yield config
17
+ finalize
18
+ end
19
+
20
+ def self.config
21
+ @config ||= WCC::Auth::Config.new
22
+ end
23
+
24
+ def self.finalize
25
+ finalize_callbacks.each(&:call)
26
+ end
27
+
28
+ def self.finalize_callbacks
29
+ @finalize_callbacks ||= []
30
+ end
31
+
32
+ end
33
+ end
@@ -0,0 +1,11 @@
1
+ $LOAD_PATH.unshift(File.join(__FILE__, "..", "..", "lib"))
2
+
3
+ require 'wcc/auth'
4
+
5
+ RSpec.configure do |config|
6
+ config.treat_symbols_as_metadata_keys_with_true_values = true
7
+ config.run_all_when_everything_filtered = true
8
+ config.filter_run :focus
9
+
10
+ config.order = 'random'
11
+ end
@@ -0,0 +1,65 @@
1
+ require 'spec_helper'
2
+
3
+ describe WCC::Auth::AccessLevel do
4
+ let(:klass) { WCC::Auth::AccessLevel }
5
+ let(:test_db) do
6
+ [
7
+ { id: 1, name: "Foo", slug: "foo", description: "foo", level: 2 },
8
+ { id: 2, name: "Bar", slug: "bar", description: "bar", level: 1 },
9
+ ]
10
+ end
11
+
12
+ describe "class indexing operators" do
13
+ subject { klass }
14
+
15
+ it "returns record by slug if symbol or string is passed" do
16
+ expect(klass["foo", test_db].level).to eq(2)
17
+ expect(klass[:bar, test_db].level).to eq(1)
18
+ end
19
+
20
+ it "returns record by level if number is passed" do
21
+ expect(klass[2, test_db].level).to eq(2)
22
+ expect(klass["1", test_db].level).to eq(1)
23
+ end
24
+
25
+ it "uses ACCESS_LEVELS db by default" do
26
+ expect(klass[:appadmin].slug).to eq("appadmin")
27
+ end
28
+ end
29
+
30
+ describe "::all class method" do
31
+ subject { klass }
32
+
33
+ it "returns array of records as listed in db argument" do
34
+ levels = subject.all(test_db)
35
+ expect(levels.count).to eq(2)
36
+ expect(levels.all? { |level| level.kind_of?(klass) }).to be_true
37
+ end
38
+
39
+ it "returns objects in level order" do
40
+ levels = subject.all(test_db)
41
+ expect(levels[0].slug).to eq("bar")
42
+ expect(levels[1].name).to eq("Foo")
43
+ end
44
+
45
+ it "uses ACCESS_LEVELS constant as DB if non provided" do
46
+ levels = subject.all
47
+ expect(levels.count).to eq(WCC::Auth::ACCESS_LEVELS.count)
48
+ expect(levels.last.slug).to eq("sysadmin")
49
+ end
50
+ end
51
+
52
+ describe "comparability" do
53
+ it "implements comparable methods" do
54
+ a = klass.new
55
+ b = klass.new
56
+ a.level = 1
57
+ b.level = 2
58
+ expect(a < b).to be_true
59
+ expect(b == a).to be_false
60
+ expect(b < a).to be_false
61
+ end
62
+ end
63
+
64
+ end
65
+
@@ -0,0 +1,21 @@
1
+ require 'spec_helper'
2
+
3
+ describe WCC::Auth::Config do
4
+ let(:klass) { WCC::Auth::Config }
5
+
6
+ describe "default attributes" do
7
+ subject { klass.new }
8
+ it "sets authorize_site according to environment" do
9
+ subject.environment = :development
10
+ expect(subject.authorize_site).to eq("http://login.dev")
11
+ subject.environment = :production
12
+ expect(subject.authorize_site).to eq("https://login.watermark.org")
13
+ end
14
+
15
+ it "sets authorize_path" do
16
+ expect(subject.authorize_path).to eq("/oauth/authorize")
17
+ end
18
+ end
19
+
20
+
21
+ end
@@ -0,0 +1,89 @@
1
+ require 'spec_helper'
2
+
3
+ describe WCC::Auth::TieredAbility do
4
+ let(:klass) { WCC::Auth::TieredAbility }
5
+ let(:access_level) { WCC::Auth::AccessLevel }
6
+
7
+ describe "defining levels" do
8
+ it "stores blocks in ::levels" do
9
+ subclass = Class.new(klass) do
10
+ at_level(:basic) {}
11
+ at_level(:contribute) {}
12
+ at_level(:basic) {}
13
+ end
14
+ expect(subclass.levels[access_level[:basic]].size).to eq(2)
15
+ expect(subclass.levels[access_level[:contribute]].size).to eq(1)
16
+ end
17
+ end
18
+
19
+ describe "#initialize" do
20
+ it "grants access to the user's access_level" do
21
+ ability = Class.new(klass) do
22
+ at_level(:basic) { |user| user.ping }
23
+ end
24
+ user = double("User")
25
+ level = double("AccessLevel")
26
+ allow(level).to receive(:>=).and_return(true)
27
+ expect(user).to receive(:access_level).and_return(level)
28
+ expect(user).to receive(:ping)
29
+ ability.new(user)
30
+ end
31
+ end
32
+
33
+ describe "#grant_access_at" do
34
+ let(:mock_klass) {
35
+ Class.new(klass) do
36
+ def initialize(mock)
37
+ @user = mock
38
+ end
39
+ end
40
+ }
41
+
42
+ it "runs only the levels that the given access level allows" do
43
+ ability = Class.new(mock_klass) do
44
+ at_level(:basic) { |mock| mock.basic }
45
+ at_level(:appadmin) { |mock| mock.appadmin }
46
+ end
47
+ mock = double
48
+ expect(mock).to receive(:basic)
49
+ ability.new(mock).grant_access_at(access_level[:manage])
50
+ end
51
+
52
+ it "runs the blocks in the defined order" do
53
+ ability = Class.new(mock_klass) do
54
+ at_level(:appadmin) { |mock| mock.first }
55
+ at_level(:basic) { |mock| mock.second }
56
+ at_level(:manage) { |mock| mock.fourth }
57
+ at_level(:basic) { |mock| mock.third }
58
+ end
59
+ mock = double
60
+ expect(mock).to receive(:first).ordered
61
+ expect(mock).to receive(:second).ordered
62
+ expect(mock).to receive(:third).ordered
63
+ expect(mock).to receive(:fourth).ordered
64
+ ability.new(mock).grant_access_at(access_level[:sysadmin])
65
+ end
66
+ end
67
+
68
+ describe "subclassing" do
69
+ it "inherits defined levels from parent class" do
70
+ sub1 = Class.new(klass) do
71
+ at_level(:basic) {}
72
+ end
73
+ sub2 = Class.new(sub1)
74
+ expect(sub2.levels.size).to eq(1)
75
+ end
76
+
77
+ it "subclass and parent class have independent levels" do
78
+ sub1 = Class.new(klass) do
79
+ at_level(:basic) {}
80
+ end
81
+ sub2 = Class.new(sub1) do
82
+ at_level(:contribute) {}
83
+ end
84
+ expect(sub1.levels.size).to eq(1)
85
+ expect(sub2.levels.size).to eq(2)
86
+ end
87
+ end
88
+
89
+ end
@@ -0,0 +1,33 @@
1
+ require 'spec_helper'
2
+
3
+ describe WCC::Auth do
4
+
5
+ before(:each) do
6
+ @previous_config = WCC::Auth.send(:instance_variable_get, :@config)
7
+ @previous_callbacks = WCC::Auth.send(:instance_variable_get, :@finalize_callbacks)
8
+ end
9
+
10
+ after(:each) do
11
+ WCC::Auth.send :instance_variable_set, :@config, @previous_config
12
+ WCC::Auth.send :instance_variable_set, :@finalize_callbacks, @previous_callbacks
13
+ end
14
+
15
+ describe "::setup class method" do
16
+ it "yields config with ::setup and sets it to ::config" do
17
+ the_config = nil
18
+ WCC::Auth.setup do |config|
19
+ expect(config).to be_a(WCC::Auth::Config)
20
+ the_config = config
21
+ end
22
+ expect(the_config).to eq(WCC::Auth.config)
23
+ end
24
+
25
+ it "calls finalize" do
26
+ ping = nil
27
+ WCC::Auth.finalize_callbacks << -> { ping = "pong" }
28
+ WCC::Auth.setup { |config| }
29
+ expect(ping).to eq("pong")
30
+ end
31
+ end
32
+
33
+ end
data/wcc-auth.gemspec ADDED
@@ -0,0 +1,29 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'wcc/auth/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "wcc-auth"
8
+ spec.version = WCC::Auth::VERSION
9
+ spec.authors = ["Travis Petticrew"]
10
+ spec.email = ["tpetticrew@watermark.org"]
11
+ spec.description = %q{Authentication / Authorization library for Watermark apps}
12
+ spec.summary = File.readlines("README.md").join
13
+ spec.homepage = "https://github.com/watermarkchurch/wcc-auth"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency "cancancan", "~> 1.9.2"
22
+ spec.add_dependency "devise", "~> 3.1"
23
+ spec.add_dependency "omniauth", "~> 1.1"
24
+ spec.add_dependency "omniauth-oauth2", "~> 1.0"
25
+
26
+ spec.add_development_dependency "bundler", "~> 1.3"
27
+ spec.add_development_dependency "rake"
28
+ spec.add_development_dependency "rspec"
29
+ end
metadata ADDED
@@ -0,0 +1,205 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: wcc-auth
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.3.0
5
+ platform: ruby
6
+ authors:
7
+ - Travis Petticrew
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-09-11 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: cancancan
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 1.9.2
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 1.9.2
27
+ - !ruby/object:Gem::Dependency
28
+ name: devise
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '3.1'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '3.1'
41
+ - !ruby/object:Gem::Dependency
42
+ name: omniauth
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.1'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.1'
55
+ - !ruby/object:Gem::Dependency
56
+ name: omniauth-oauth2
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '1.0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '1.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: bundler
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '1.3'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '1.3'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rake
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rspec
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ description: Authentication / Authorization library for Watermark apps
112
+ email:
113
+ - tpetticrew@watermark.org
114
+ executables: []
115
+ extensions: []
116
+ extra_rdoc_files: []
117
+ files:
118
+ - ".gitignore"
119
+ - ".rspec"
120
+ - Gemfile
121
+ - LICENSE.txt
122
+ - README.md
123
+ - Rakefile
124
+ - lib/omniauth/strategies/watermark.rb
125
+ - lib/wcc/auth.rb
126
+ - lib/wcc/auth/ability.rb
127
+ - lib/wcc/auth/access_level.rb
128
+ - lib/wcc/auth/config.rb
129
+ - lib/wcc/auth/controller_helpers.rb
130
+ - lib/wcc/auth/devise.rb
131
+ - lib/wcc/auth/devise/watermark_callbacks_controller.rb
132
+ - lib/wcc/auth/providers.rb
133
+ - lib/wcc/auth/providers/active_record.rb
134
+ - lib/wcc/auth/version.rb
135
+ - spec/spec_helper.rb
136
+ - spec/wcc/auth/access_level_spec.rb
137
+ - spec/wcc/auth/config_spec.rb
138
+ - spec/wcc/auth/tiered_ability_spec.rb
139
+ - spec/wcc_auth_spec.rb
140
+ - wcc-auth.gemspec
141
+ homepage: https://github.com/watermarkchurch/wcc-auth
142
+ licenses:
143
+ - MIT
144
+ metadata: {}
145
+ post_install_message:
146
+ rdoc_options: []
147
+ require_paths:
148
+ - lib
149
+ required_ruby_version: !ruby/object:Gem::Requirement
150
+ requirements:
151
+ - - ">="
152
+ - !ruby/object:Gem::Version
153
+ version: '0'
154
+ required_rubygems_version: !ruby/object:Gem::Requirement
155
+ requirements:
156
+ - - ">="
157
+ - !ruby/object:Gem::Version
158
+ version: '0'
159
+ requirements: []
160
+ rubyforge_project:
161
+ rubygems_version: 2.2.2
162
+ signing_key:
163
+ specification_version: 4
164
+ summary: '# WCC::Auth Provides the necessary tools for handling authentication through
165
+ Watermark''s OAuth provider as well as authorizing the user has access to specific
166
+ features within the application. There are special hooks for Rails apps using Devise,
167
+ but the primitive structures could be used on any Ruby project. Currently, the only
168
+ tested path is Rails with Devise. ## Installation Add this line to your application''s
169
+ Gemfile: ```ruby gem ''wcc-auth'', ''~> 0.3.0'' ``` If you are using a Rails app
170
+ with Devise you can use a special require hook that will setup all the Devise specific
171
+ configuration for you. ```ruby gem ''wcc-auth'', ''~> 0.3.0'', require: ''wcc/auth/devise''
172
+ ``` ## Configuration There are a few steps to setup your app. These instructions
173
+ are specific to a Rails app. #### Add the configuration block to an initializer In
174
+ order to configure the gem you must run the `WCC::Auth.setup` block. See below for
175
+ an example: ```ruby WCC::Auth.setup do |config| config.app_name = "app-name" config.environment
176
+ = Rails.env config.app_id = ''app-client-id-from-oauth-provider'' config.app_secret
177
+ = ''app-client-secret-from-oauth-provider'' end ``` #### Setup your controllers ```ruby
178
+ # Add this include to your ApplicationController class ApplicationController < ActionController::Base
179
+ include WCC::Auth::ControllerHelpers end ``` #### Setup your user model ```ruby
180
+ class User < ActiveRecord::Base include WCC::Auth::Providers::ActiveRecord # ... end
181
+ ``` #### Setup authorization (optional) If you would like to use the `TieredAbility`
182
+ class included with `WCC::Auth` just create an Ability class that extends the `WCC::Auth::TieredAbility`
183
+ class. The authenticated user will include an info variables called `access_level_id`.
184
+ This corresponds to a `WCC::Auth::AccessLevel`. The access levels are broken down
185
+ into 5 tiers with the following rules: * **No access** -- This is the default level
186
+ * **Basic** -- This is provides read-only access * **Contribute** -- Read-write
187
+ for only data the user owns * **Manage** -- Read-write for other''s data * **App
188
+ Admin** -- Can change app configuration * **System Admin** -- Has full access to
189
+ all features always Each tier inherits all priveleges of the lower tiers. The rules
190
+ here are guidelines for the app to follow. It is ultimately up to the client application
191
+ to decide what each of these tiers means for it. Do your best to adhere to these
192
+ rules. Here is an example Ability class using the DSL provided by `WCC::Auth`. ```ruby
193
+ class Ability < WCC::Auth::TieredAbility at_level(:contribute) do |user| can :read,
194
+ Person can :manage, Task, created_by_id: user.id can :manage, Comment, created_by_id:
195
+ user.id cannot :destroy, Task end at_level(:appadmin) do |user| can :manage, :all
196
+ cannot :create, TaskGroup end at_level(:sysadmin) do |user| can :manage, :all
197
+ end end ``` ## Contributing 1. Fork it 2. Create your feature branch (`git checkout
198
+ -b my-new-feature`) 3. Commit your changes (`git commit -am ''Add some feature''`)
199
+ 4. Push to the branch (`git push origin my-new-feature`) 5. Create new Pull Request'
200
+ test_files:
201
+ - spec/spec_helper.rb
202
+ - spec/wcc/auth/access_level_spec.rb
203
+ - spec/wcc/auth/config_spec.rb
204
+ - spec/wcc/auth/tiered_ability_spec.rb
205
+ - spec/wcc_auth_spec.rb