disiid_user 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/.gitignore ADDED
@@ -0,0 +1,8 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
5
+ .rvmrc*
6
+ rvmrc*
7
+ !.rvmrc-template
8
+
data/.rvmrc-template ADDED
@@ -0,0 +1 @@
1
+ rvm 1.9.2-p180@rails3 --create
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in disiid_user.gemspec
4
+ gemspec
data/Rakefile ADDED
@@ -0,0 +1,5 @@
1
+ require 'rspec/core/rake_task'
2
+ RSpec::Core::RakeTask.new('spec')
3
+
4
+ desc "Run tests"
5
+ task :default => :spec
@@ -0,0 +1,29 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "disiid_user/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "disiid_user"
7
+ s.version = DisiidUser::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Danilo Severina", "Alex Vagin"]
10
+ s.email = ["tech@disi.unitn.it"]
11
+ s.homepage = "http://disi.unitn.it"
12
+ s.summary = %q{DISI ID global user}
13
+ s.description = %q{DISI - UniTN internal development}
14
+
15
+ s.required_rubygems_version = ">= 1.3.6"
16
+ s.rubyforge_project = "disiid_user"
17
+
18
+ s.files = `git ls-files`.split("\n")
19
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
20
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
21
+ s.require_paths = ["lib"]
22
+
23
+ # specify any dependencies here; for example:
24
+ s.add_development_dependency "rspec"
25
+ s.add_development_dependency "rake", '~> 0.8.7'
26
+ s.add_development_dependency "bundler"
27
+ # runtime dependencies
28
+ s.add_runtime_dependency "activeresource", '~> 2'
29
+ end
@@ -0,0 +1,3 @@
1
+ module DisiidUser
2
+ VERSION = "2.0.1"
3
+ end
@@ -0,0 +1,114 @@
1
+ require "disiid_user/version"
2
+ require 'active_resource'
3
+
4
+ ## Usage:
5
+ #
6
+ # in config/initializers/disid.rb:
7
+ #
8
+ # DisiidUser::RemoteUser.site = 'http://id.provider.com'
9
+ # DisiidUser::RemoteUser.auth_token = 'a secret token goes here'
10
+ #
11
+ # # if resource name is different from 'user' (default)
12
+ # DisiidUser::RemoteUser.element_name = 'user'
13
+ #
14
+ # in app/models/user.rb:
15
+ #
16
+ # class User < ActiveRecord::Base
17
+ # include DisiidUser
18
+ # ...
19
+ # end
20
+ #
21
+ module DisiidUser
22
+
23
+ def self.included(klass)
24
+ klass.class_eval do
25
+ named_scope :with_local_role, lambda { |role| where('role & ? > 0', 2**LOCAL_ROLES.index(role.to_s)) }
26
+ end
27
+ end
28
+
29
+ def self.version_string
30
+ "DisiidUser version #{VERSION}"
31
+ end
32
+
33
+ ########################################################################
34
+ # Check roles of user
35
+ #
36
+
37
+ # list of local roles
38
+ LOCAL_ROLES = %w(admin manager) unless defined? LOCAL_ROLES
39
+
40
+ # list of methid name that could be called from User instance to get data
41
+ # from the RemoteUser instance
42
+ REMOTE_ATTRIBUTES = %w(email first_name last_name homepage) unless defined? REMOTE_ATTRIBUTES
43
+
44
+ # List of roles for local setup
45
+ def local_roles
46
+ LOCAL_ROLES.reject { |r| ((role || 0) & 2**LOCAL_ROLES.index(r)).zero? }
47
+ end
48
+
49
+ # Add roles to the local setup
50
+ # all of the following will work:
51
+ # user.local_roles = :admin
52
+ # user.local_roles = [:admin, :manager]
53
+ # user.local_roles = 'admin'
54
+ # user.local_roles = 'admin', 'manager' # w/o brackets
55
+ def local_roles=(*roles)
56
+ self.role = (roles.flatten.map { |r| r.to_s } & LOCAL_ROLES).map { |r| 2**LOCAL_ROLES.index(r) }.sum
57
+ end
58
+
59
+ # List of roles both local and remote (no duplicates)
60
+ def roles
61
+ @roles ||= remote_user ? (local_roles + remote_user.roles).uniq : local_roles
62
+ end
63
+
64
+ # Check if the user has the required role
65
+ # admin role has all privileges
66
+ # has_role? 'manager'
67
+ # has_role? :admin
68
+ def has_role?(role)
69
+ roles.include?("admin") || roles.include?(role.to_s)
70
+ end
71
+
72
+ ########################################################################
73
+ # Method for interaction with RemoteUser
74
+ #
75
+
76
+ # Method for requesting data of remote user
77
+ REMOTE_ATTRIBUTES.each do |remote_attr|
78
+ define_method remote_attr do
79
+ remote_user.try(remote_attr)
80
+ end
81
+ end
82
+
83
+ # Get the remote user via get ActiveResource
84
+ def remote_user
85
+ @remote_user ||= DisiidUser::RemoteUser.find uuid, :params => { :auth_token => DisiidUser::RemoteUser.auth_token }
86
+ rescue
87
+ nil
88
+ end
89
+
90
+ # Return the uuid of a user
91
+ # Last part of identity_url, after path 'user' (element_name of RemoteUser params)
92
+ def uuid
93
+ @uuid ||= begin
94
+ collection_name = DisiidUser::RemoteUser.collection_name
95
+ /.*\/#{collection_name}\/([a-z0-9\-]+)$/.match(identity_url.to_s)[1]
96
+ rescue; nil; end
97
+ end
98
+
99
+ #######################################################################
100
+ # Class RemoteUser
101
+ # interact with remote server to get user information: personal data and roles
102
+ # active resource
103
+ #
104
+
105
+ # ROLES defined here must be EQUAL with the one defined remote Class self.site
106
+ class RemoteUser < ActiveResource::Base
107
+ self.site = 'http://localhost:3001'
108
+ self.element_name = 'user'
109
+ self.format = :json
110
+ cattr_accessor :auth_token
111
+ end
112
+
113
+ end
114
+
@@ -0,0 +1,15 @@
1
+ {
2
+ "uuid": "596568c5-d6e7-4328-815c-c532aeed1198",
3
+ "email":"nobody@example.org",
4
+ "first_name":"Mr",
5
+ "last_name":"Anonymous",
6
+ "nickname":"mr.anon",
7
+ "photo": "nobody.jpg",
8
+ "homepage":"",
9
+ "office_address":"via sommarive, 5",
10
+ "office_num":"D44",
11
+ "office_phone":"0461444444",
12
+ "office_fax":"0461555555",
13
+ "roles": []
14
+ }
15
+
@@ -0,0 +1,15 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <user>
3
+ <uuid>596568c5-d6e7-4328-815c-c532aeed1198</uuid>
4
+ <email>nobody@example.org</email>
5
+ <first-name>Mr</first-name>
6
+ <last-name>Anonymous</last-name>
7
+ <nickname>mr.anon</nickname>
8
+ <photo>nobody.jpg</photo>
9
+ <homepage nil="true"></homepage>
10
+ <office-address>via sommarive, 5</office-address>
11
+ <office-num>D44</office-num>
12
+ <office-phone>0461444444</office-phone>
13
+ <office-fax>0461555555</office-fax>
14
+ <roles type="array"></roles>
15
+ </user>
@@ -0,0 +1,15 @@
1
+ {
2
+ "uuid": "6a002a40-bc63-4095-9bb0-f31bf386bf55",
3
+ "email":"admin@example.org",
4
+ "first_name":"John",
5
+ "last_name":"Smith",
6
+ "nickname":"john.smith",
7
+ "photo": "avatar.jpg",
8
+ "homepage":"http://john.smith.example.org",
9
+ "office_address":"via sommarive, 5",
10
+ "office_num":"D14",
11
+ "office_phone":"0461012345",
12
+ "office_fax":"0461540123",
13
+ "roles":["admin","whatever"]
14
+ }
15
+
@@ -0,0 +1,18 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <user>
3
+ <uuid>6a002a40-bc63-4095-9bb0-f31bf386bf55</uuid>
4
+ <email>admin@example.org</email>
5
+ <first-name>John</first-name>
6
+ <last-name>Smith</last-name>
7
+ <nickname>john.smith</nickname>
8
+ <photo>avatar.jpg</photo>
9
+ <homepage>http://john.smith.example.org</homepage>
10
+ <office-address>via sommarive, 5</office-address>
11
+ <office-num>D14</office-num>
12
+ <office-phone>0461012345</office-phone>
13
+ <office-fax>0461540123</office-fax>
14
+ <roles type="array">
15
+ <role>admin</role>
16
+ <role>whatever</role>
17
+ </roles>
18
+ </user>
@@ -0,0 +1,146 @@
1
+ require 'spec_helper'
2
+ require 'user'
3
+
4
+ # admin@example.org
5
+ # 6a002a40-bc63-4095-9bb0-f31bf386bf55
6
+ # admin
7
+
8
+ # nobody@example.org
9
+ # 596568c5-d6e7-4328-815c-c532aeed1198
10
+ # no role
11
+
12
+ describe DisiidUser do
13
+
14
+ before { @user = User.new }
15
+
16
+ it 'should return correct version string' do
17
+ DisiidUser.version_string.should == "DisiidUser version #{DisiidUser::VERSION}"
18
+ end
19
+
20
+ it 'should extract uuid from identity_url' do
21
+ @user.identity_url = "http://openid.provider.local/users/6a002a40-bc63-4095-9bb0-f31bf386bf55"
22
+ @user.uuid.should == "6a002a40-bc63-4095-9bb0-f31bf386bf55"
23
+ end
24
+
25
+ it 'should return nil if identity_url is of unknown nature' do
26
+ @user.identity_url = "http://openid.provider.local/6a002a40-bc63-4095-9bb0-f31bf386bf55"
27
+ @user.uuid.should be_nil
28
+ end
29
+
30
+ it 'should return nil if identity_url is not defined' do
31
+ @user.identity_url = ""
32
+ @user.uuid.should be_nil
33
+
34
+ # uuid is not memorized so we're safe to reuse @user instance
35
+ @user.identity_url = nil
36
+ @user.uuid.should be_nil
37
+ end
38
+
39
+ context "with local roles" do
40
+
41
+ it 'should correctly parse :role attribute' do
42
+ @user.role = 1
43
+ @user.local_roles.should include 'admin'
44
+ @user.local_roles.length.should == 1
45
+
46
+ @user.role = 3
47
+ @user.local_roles.should include 'admin'
48
+ @user.local_roles.should include 'manager'
49
+ @user.local_roles.length.should == 2
50
+ end
51
+
52
+ it 'should correctly set :role attribute' do
53
+ @user.local_roles = 'admin', 'manager'
54
+ @user.role.should == 3
55
+
56
+ @user.local_roles = ['manager']
57
+ @user.role.should == 2
58
+ end
59
+
60
+ describe 'has_role?() method' do
61
+
62
+ it 'should use roles()' do
63
+ @user.should_receive(:roles).at_least(:once).and_return([])
64
+ @user.has_role?("does't matter")
65
+ end
66
+
67
+ context 'when admin' do
68
+ before { @user.role = 1 }
69
+
70
+ it 'should always return true' do
71
+ @user.has_role?('admin').should be true
72
+ @user.has_role?('manager').should be true
73
+ end
74
+ end
75
+
76
+ context 'when manager' do
77
+ before { @user.local_roles = :manager }
78
+
79
+ it 'should not be admin' do
80
+ @user.has_role?(:admin).should_not be true
81
+ end
82
+
83
+ it 'should not be something else' do
84
+ @user.has_role?('something').should_not be true
85
+ end
86
+
87
+ it 'should be manager' do
88
+ @user.has_role?('manager').should be true
89
+ end
90
+ end # context 'when manager'
91
+ end # describe 'has_role?() method'
92
+ end # context "with local roles"
93
+
94
+ context 'with remote user' do
95
+ before { DisiidUser::RemoteUser.auth_token = 'sometoken' }
96
+
97
+ it 'should fetch it using find()' do
98
+ DisiidUser::RemoteUser.should_receive(:find).with('some-uuid', :params => hash_including(:auth_token => 'sometoken'))
99
+ @user.identity_url = "http://host/users/some-uuid"
100
+ @user.remote_user
101
+ end
102
+
103
+ context 'when does not exist' do
104
+ before { @user.identity_url = "http://openid.provider.local/users/does-no-exist" }
105
+ it 'should just be nil' do
106
+ @user.remote_user.should be_nil
107
+ end
108
+
109
+ it 'should return nil for remote attributes' do
110
+ @user.email.should be_nil
111
+ @user.homepage.should be_nil
112
+ @user.first_name.should be_nil
113
+ @user.last_name.should be_nil
114
+ end
115
+ end
116
+
117
+ context 'when exists' do
118
+ before {
119
+ @user.identity_url = "http://openid.provider.local/users/6a002a40-bc63-4095-9bb0-f31bf386bf55"
120
+ }
121
+
122
+ it 'should have remote attributes' do
123
+ @user.email.should == 'admin@example.org'
124
+ @user.first_name.should == 'John'
125
+ @user.last_name.should == 'Smith'
126
+ @user.homepage.should == 'http://john.smith.example.org'
127
+ end
128
+
129
+ it 'should get all roles, including remote' do
130
+ @user.local_roles = 'manager'
131
+ @user.roles.should include 'admin' # remote
132
+ @user.roles.should include 'manager' # local
133
+ end
134
+
135
+ it 'should not have duplicated roles' do
136
+ @user.local_roles = 'admin', 'manager'
137
+ # this remote user has two roles, :admin and :whatever
138
+ # spec/6a002a40-bc63-4095-9bb0-f31bf386bf55.xml
139
+ %w(admin manager whatever).each { |r|
140
+ @user.roles.should include r
141
+ }
142
+ @user.roles.length.should == 3
143
+ end
144
+ end # context 'when exists'
145
+ end # context 'with remote user'
146
+ end
@@ -0,0 +1,10 @@
1
+ require 'spec_helper'
2
+
3
+ describe DisiidUser::RemoteUser do
4
+ let(:remote_user_class) { DisiidUser::RemoteUser }
5
+
6
+ it "should have :auth_token class attribute accessor" do
7
+ remote_user_class.auth_token = 'mysecrettoken'
8
+ remote_user_class.auth_token.should == 'mysecrettoken'
9
+ end
10
+ end
@@ -0,0 +1,7 @@
1
+ require 'rspec'
2
+ require 'disiid_user'
3
+
4
+ RSpec.configure do |config|
5
+ config.color_enabled = true
6
+ config.formatter = 'documentation'
7
+ end
@@ -0,0 +1,10 @@
1
+ require 'spec_helper'
2
+ require 'user'
3
+
4
+ # stub methods check
5
+ describe Array do
6
+ it 'should return sum of array' do
7
+ [1,2,3,4].sum.should == 10
8
+ [10,20,30,40].sum.should == 100
9
+ end
10
+ end
data/spec/user.rb ADDED
@@ -0,0 +1,38 @@
1
+ # Method define in Activesupport
2
+ class Array
3
+ def sum
4
+ return self.inject{|sum,x| sum + x }
5
+ end
6
+ end
7
+
8
+ # dummy User class for testing.
9
+ # in real app it should be subclassed from ActiveRecord::Base
10
+ # and have at least these attributes:
11
+ # - role (Integer)
12
+ # - identity_url (String)
13
+ class User
14
+ # stub methods and attributes
15
+ def self.named_scope(*args); end
16
+ attr_accessor :role, :identity_url
17
+
18
+ include DisiidUser
19
+ end
20
+
21
+ # Stub ActiveRecord so that it won't do real HTTP requests
22
+ module ActiveResource
23
+ class Connection
24
+ # taps into ActiveRecord to read data from stub files
25
+ # instead of doing a real HTTP request
26
+ def get(path, *args)
27
+ record = /\/[^\/]+\/([^\/]+)/.match(path)[1]
28
+ # record string includes .xml or .json too
29
+ filename = "#{File.dirname(__FILE__)}/#{record}".sub(/\?.*$/, '')
30
+ # format is either ActiveResource::Formats::XmlFormat or JsonFormat
31
+ # 3.0.x defaults to XML, 3.1.x defaults to JSON
32
+ format.decode open(filename).read
33
+ rescue
34
+ #raise ActiveResource::ResourceNotFound.new("dummy remote user didn't find that resource: #{path} #{args.inspect}")
35
+ nil
36
+ end
37
+ end
38
+ end
metadata ADDED
@@ -0,0 +1,151 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: disiid_user
3
+ version: !ruby/object:Gem::Version
4
+ hash: 13
5
+ prerelease:
6
+ segments:
7
+ - 2
8
+ - 0
9
+ - 1
10
+ version: 2.0.1
11
+ platform: ruby
12
+ authors:
13
+ - Danilo Severina
14
+ - Alex Vagin
15
+ autorequire:
16
+ bindir: bin
17
+ cert_chain: []
18
+
19
+ date: 2011-11-16 00:00:00 +01:00
20
+ default_executable:
21
+ dependencies:
22
+ - !ruby/object:Gem::Dependency
23
+ name: rspec
24
+ prerelease: false
25
+ requirement: &id001 !ruby/object:Gem::Requirement
26
+ none: false
27
+ requirements:
28
+ - - ">="
29
+ - !ruby/object:Gem::Version
30
+ hash: 3
31
+ segments:
32
+ - 0
33
+ version: "0"
34
+ type: :development
35
+ version_requirements: *id001
36
+ - !ruby/object:Gem::Dependency
37
+ name: rake
38
+ prerelease: false
39
+ requirement: &id002 !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - ~>
43
+ - !ruby/object:Gem::Version
44
+ hash: 49
45
+ segments:
46
+ - 0
47
+ - 8
48
+ - 7
49
+ version: 0.8.7
50
+ type: :development
51
+ version_requirements: *id002
52
+ - !ruby/object:Gem::Dependency
53
+ name: bundler
54
+ prerelease: false
55
+ requirement: &id003 !ruby/object:Gem::Requirement
56
+ none: false
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ hash: 3
61
+ segments:
62
+ - 0
63
+ version: "0"
64
+ type: :development
65
+ version_requirements: *id003
66
+ - !ruby/object:Gem::Dependency
67
+ name: activeresource
68
+ prerelease: false
69
+ requirement: &id004 !ruby/object:Gem::Requirement
70
+ none: false
71
+ requirements:
72
+ - - ~>
73
+ - !ruby/object:Gem::Version
74
+ hash: 7
75
+ segments:
76
+ - 2
77
+ version: "2"
78
+ type: :runtime
79
+ version_requirements: *id004
80
+ description: DISI - UniTN internal development
81
+ email:
82
+ - tech@disi.unitn.it
83
+ executables: []
84
+
85
+ extensions: []
86
+
87
+ extra_rdoc_files: []
88
+
89
+ files:
90
+ - .gitignore
91
+ - .rvmrc-template
92
+ - Gemfile
93
+ - Rakefile
94
+ - disiid_user.gemspec
95
+ - lib/disiid_user.rb
96
+ - lib/disiid_user/version.rb
97
+ - spec/596568c5-d6e7-4328-815c-c532aeed1198.json
98
+ - spec/596568c5-d6e7-4328-815c-c532aeed1198.xml
99
+ - spec/6a002a40-bc63-4095-9bb0-f31bf386bf55.json
100
+ - spec/6a002a40-bc63-4095-9bb0-f31bf386bf55.xml
101
+ - spec/disiid_user_spec.rb
102
+ - spec/remote_user_spec.rb
103
+ - spec/spec_helper.rb
104
+ - spec/stub_methods_spec.rb
105
+ - spec/user.rb
106
+ has_rdoc: true
107
+ homepage: http://disi.unitn.it
108
+ licenses: []
109
+
110
+ post_install_message:
111
+ rdoc_options: []
112
+
113
+ require_paths:
114
+ - lib
115
+ required_ruby_version: !ruby/object:Gem::Requirement
116
+ none: false
117
+ requirements:
118
+ - - ">="
119
+ - !ruby/object:Gem::Version
120
+ hash: 3
121
+ segments:
122
+ - 0
123
+ version: "0"
124
+ required_rubygems_version: !ruby/object:Gem::Requirement
125
+ none: false
126
+ requirements:
127
+ - - ">="
128
+ - !ruby/object:Gem::Version
129
+ hash: 23
130
+ segments:
131
+ - 1
132
+ - 3
133
+ - 6
134
+ version: 1.3.6
135
+ requirements: []
136
+
137
+ rubyforge_project: disiid_user
138
+ rubygems_version: 1.4.1
139
+ signing_key:
140
+ specification_version: 3
141
+ summary: DISI ID global user
142
+ test_files:
143
+ - spec/596568c5-d6e7-4328-815c-c532aeed1198.json
144
+ - spec/596568c5-d6e7-4328-815c-c532aeed1198.xml
145
+ - spec/6a002a40-bc63-4095-9bb0-f31bf386bf55.json
146
+ - spec/6a002a40-bc63-4095-9bb0-f31bf386bf55.xml
147
+ - spec/disiid_user_spec.rb
148
+ - spec/remote_user_spec.rb
149
+ - spec/spec_helper.rb
150
+ - spec/stub_methods_spec.rb
151
+ - spec/user.rb