roles_data_mapper 0.1.0

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/.document ADDED
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
data/.gitignore ADDED
@@ -0,0 +1,21 @@
1
+ ## MAC OS
2
+ .DS_Store
3
+
4
+ ## TEXTMATE
5
+ *.tmproj
6
+ tmtags
7
+
8
+ ## EMACS
9
+ *~
10
+ \#*
11
+ .\#*
12
+
13
+ ## VIM
14
+ *.swp
15
+
16
+ ## PROJECT::GENERAL
17
+ coverage
18
+ rdoc
19
+ pkg
20
+
21
+ ## PROJECT::SPECIFIC
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --format nested --color
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Kristian Mandrup
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.markdown ADDED
@@ -0,0 +1,59 @@
1
+ # Roles for Data Mapper
2
+
3
+ A Data Mapper implementation of [roles generic](http://github.com/kristianmandrup/roles_generic)
4
+
5
+ ## Update!
6
+
7
+ Now implements the [roles generic](http://github.com/kristianmandrup/roles_generic) Roles API
8
+ It also implements the following Role strategies:
9
+
10
+ * admin_flag
11
+ * many_roles
12
+ * one_role
13
+ * roles_mask
14
+ * role_string
15
+
16
+ See [roles_active_record](http://github.com/kristianmandrup/roles_active_record) and [roles generic](http://github.com/kristianmandrup/roles_generic) for more info on using the API.
17
+
18
+ ## Install
19
+
20
+ <code>gem install roles_data_mapper</code>
21
+
22
+ To install from cloned repo:
23
+
24
+ This gem is based on Jeweler, so simply:
25
+
26
+ <code>rake install</code>
27
+
28
+ ## Rails generator
29
+
30
+ _Note_:
31
+
32
+ *The Rails generator is a bit "rusty" and hasn't been tested with the latest changes. I hope to update it soon.*
33
+
34
+ The library comes with a Rails 3 generator that lets you populate a user model with a given role strategy
35
+ The following role strategies are included by default. Add your own by adding extra files inside the strategy folder, one file for each role strategy is recommended.
36
+
37
+ * admin_flag
38
+ * inline_role
39
+ * inline_roles
40
+ * role_relations
41
+ * role_mask
42
+
43
+ Example:
44
+
45
+ <code>$ rails g data_mapper:roles User --strategy admin_flag</code>
46
+
47
+ ## Note on Patches/Pull Requests
48
+
49
+ * Fork the project.
50
+ * Make your feature addition or bug fix.
51
+ * Add tests for it. This is important so I don't break it in a
52
+ future version unintentionally.
53
+ * Commit, do not mess with rakefile, version, or history.
54
+ (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
55
+ * Send me a pull request. Bonus points for topic branches.
56
+
57
+ ## Copyright
58
+
59
+ Copyright (c) 2010 Kristian Mandrup. See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,27 @@
1
+ begin
2
+ require 'jeweler'
3
+ Jeweler::Tasks.new do |gem|
4
+ gem.name = "roles_data_mapper"
5
+ gem.summary = %Q{Implementation of Roles generic API for DataMapper}
6
+ gem.description = %Q{Makes it easy to set a role strategy on your User model in DataMapper}
7
+ gem.email = "kmandrup@gmail.com"
8
+ gem.homepage = "http://github.com/kristianmandrup/roles_for_dm"
9
+ gem.authors = ["Kristian Mandrup"]
10
+ gem.add_development_dependency "rspec", ">= 2.0.0.beta.19"
11
+
12
+ gem.add_dependency "dm-core", "~> 1.0"
13
+ gem.add_dependency "dm-types", "~> 1.0"
14
+ gem.add_dependency "dm-migrations", "~> 1.0"
15
+
16
+ gem.add_dependency "activesupport", "~> 3.0.0"
17
+ gem.add_dependency "require_all", '~> 1.1.0'
18
+ gem.add_dependency "sugar-high", '~> 0.2.3'
19
+ gem.add_dependency "roles_generic", '~> 0.2.2'
20
+
21
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
22
+ end
23
+ Jeweler::GemcutterTasks.new
24
+ rescue LoadError
25
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
26
+ end
27
+
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
@@ -0,0 +1,74 @@
1
+ require 'rails3_artifactor'
2
+ require 'logging_assist'
3
+
4
+ puts "Included!"
5
+
6
+ module DataMapper
7
+ module Generators
8
+ class RolesGenerator < Rails::Generators::NamedBase
9
+ desc "Add role strategy to a model"
10
+
11
+ class_option :strategy, :type => :string, :aliases => "-s", :default => 'role_string',
12
+ :desc => "Role strategy to use (admin_flag, role_string, roles_string, role_strings, one_role, many_roles, roles_mask)"
13
+
14
+
15
+ class_option :roles, :type => :array, :aliases => "-r", :default => [], :desc => "Valid roles"
16
+
17
+ def apply_role_strategy
18
+ log.add_logfile
19
+ log.debug "apply_role_strategy for : #{strategy} in model #{name}"
20
+ begin
21
+ insert_into_model name do
22
+ insertion_text
23
+ end
24
+ rescue
25
+ say "Model #{name} not found"
26
+ end
27
+ end
28
+
29
+ protected
30
+
31
+ extend Rails3::Assist::UseMacro
32
+ use_orm :data_mapper
33
+ include Rails::Assist::BasicLogging
34
+
35
+ def orm
36
+ :data_mapper
37
+ end
38
+
39
+ def default_roles
40
+ [:admin, :guest]
41
+ end
42
+
43
+ def roles_to_add
44
+ @roles_to_add ||= default_roles.concat(options[:roles]).to_symbols.uniq
45
+ end
46
+
47
+ def roles
48
+ roles_to_add.map{|r| ":#{r}" }
49
+ end
50
+
51
+ def role_strategy_statement
52
+ "strategy :#{strategy}, :default\n#{role_class_stmt}"
53
+ end
54
+
55
+ def role_class_stmt
56
+ " role_class :role" if [:one_role, :many_roles].include? (strategy.to_sym)
57
+ end
58
+
59
+ def roles_statement
60
+ roles ? "valid_roles_are #{roles.join(', ')}" : ''
61
+ end
62
+
63
+ def insertion_text
64
+ %Q{include Roles::#{orm.to_s.camelize}
65
+ #{role_strategy_statement}
66
+ #{roles_statement}}
67
+ end
68
+
69
+ def strategy
70
+ options[:strategy]
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,32 @@
1
+ module Roles::Base
2
+ def valid_roles_are(*role_list)
3
+ strategy_class.valid_roles = role_list.to_symbols
4
+ end
5
+ end
6
+
7
+ module Roles
8
+ module DataMapper
9
+ def self.included(base)
10
+ base.extend Roles::Base
11
+ base.extend ClassMethods
12
+ base.orm_name = :data_mapper
13
+ end
14
+
15
+ module ClassMethods
16
+
17
+ MAP = {
18
+ :admin_flag => "property :admin_flag, ::DataMapper::Property::Flag[:admin, :default]",
19
+ :roles_mask => "property :roles_mask, Integer, :default => 1",
20
+ :role_string => "property :role_string, String",
21
+ :roles_string => "property :roles_string, String"
22
+ }
23
+
24
+ def strategy name, options=nil
25
+ if options == :default && MAP[name]
26
+ instance_eval MAP[name]
27
+ end
28
+ role_strategy name, options
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,12 @@
1
+ require 'sugar-high/module'
2
+
3
+ module Roles
4
+ modules :data_mapper do
5
+ nested_modules :user, :role
6
+ end
7
+ modules :base, :strategy
8
+ end
9
+
10
+ module RoleStrategy
11
+ modules :data_mapper
12
+ end
@@ -0,0 +1,30 @@
1
+ module Roles::Base
2
+ def valid_roles_are(*role_list)
3
+ strategy_class.valid_roles = role_list.to_symbols
4
+ if role_class_name
5
+ role_list.each do |name|
6
+ role = role_class_name.create(:name => name.to_s)
7
+ role.save
8
+ end
9
+ end
10
+ end
11
+ end
12
+
13
+ class Role
14
+ include DataMapper::Resource
15
+
16
+ property :id, Serial
17
+ property :name, String
18
+
19
+ class << self
20
+ def find_roles(*role_names)
21
+ all(:name => role_names.flatten)
22
+ end
23
+
24
+ def find_role role_name
25
+ raise ArgumentError, "#find_role takes a single role name as argument, not: #{role_name.inspect}" if !role_name.kind_of_label?
26
+ res = find_roles(role_name)
27
+ res ? res.first : res
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,85 @@
1
+ class Role
2
+ def self.named role_names
3
+ where(:name.in => role_names.flatten)
4
+ end
5
+
6
+ property :id, Serial
7
+ has n, :user_roles
8
+ has n, :users, :through => :user_roles
9
+ end
10
+
11
+ class UserRole
12
+ include DataMapper::Resource
13
+
14
+ belongs_to :user, 'User', :key => true
15
+ belongs_to :role, 'Role', :key => true
16
+ end
17
+
18
+
19
+ module RoleStrategy::DataMapper
20
+ module ManyRoles
21
+ def self.default_role_attribute
22
+ :many_roles
23
+ end
24
+
25
+ def self.included base
26
+ base.extend Roles::Generic::Role::ClassMethods
27
+ base.extend ClassMethods
28
+ base.instance_eval %{
29
+ has n, :user_roles
30
+ has n, :many_roles, 'Role', :through => :user_roles, :via => :role
31
+ }
32
+ end
33
+
34
+ module ClassMethods
35
+ def role_attribute
36
+ strategy_class.roles_attribute_name
37
+ end
38
+
39
+ def in_role(role_name)
40
+ role = Role.all(:name => role_name).first
41
+ all("user_roles.role_id" => role.id)
42
+ end
43
+
44
+ def in_roles(*roles)
45
+ role_ids = Role.all(:name.in => roles.flatten).map{|role| role.id}
46
+ all("user_roles.role_id" => role_ids)
47
+ end
48
+ end
49
+
50
+ module Implementation
51
+ def role_attribute
52
+ strategy_class.roles_attribute_name
53
+ end
54
+
55
+ # assign roles
56
+ def roles=(*roles)
57
+ raise "Role class #{role_class} does not have a #find_role(role) method" if !role_class.respond_to? :find_role
58
+ role_relations = role_class.find_roles(*roles)
59
+ self.send("#{role_attribute}=", role_relations)
60
+ self.save
61
+ end
62
+
63
+ def add_roles(*roles)
64
+ raise "Role class #{role_class} does not have a #find_role(role) method" if !role_class.respond_to? :find_role
65
+ role_relations = role_class.find_roles(*roles)
66
+ role_relations.each do |rel|
67
+ self.send(role_attribute) << rel
68
+ end
69
+ end
70
+
71
+ # query assigned roles
72
+ def roles
73
+ self.send(role_attribute)
74
+ end
75
+
76
+ def roles_list
77
+ [roles].flatten.map{|r| r.name }.compact.to_symbols
78
+ end
79
+ end
80
+
81
+ extend Roles::Generic::User::Configuration
82
+ configure :type => :role_class
83
+ end
84
+ end
85
+
@@ -0,0 +1,81 @@
1
+ module RoleStrategy::DataMapper
2
+ module RolesMask
3
+ def self.default_role_attribute
4
+ :roles_mask
5
+ end
6
+
7
+ def self.included base
8
+ base.extend ClassMethods
9
+ end
10
+
11
+ module ClassMethods
12
+ def role_attribute
13
+ strategy_class.roles_attribute_name.to_sym
14
+ end
15
+
16
+ def in_role(role)
17
+ mask = calc_index(role.to_s)
18
+ all.select do |user|
19
+ (user.send(role_attribute) & mask) > 0
20
+ end
21
+ end
22
+
23
+ def in_roles(*roles)
24
+ all.select do |user|
25
+ roles.flatten.any? do |role|
26
+ mask = calc_index(role.to_s)
27
+ (user.send(role_attribute) & mask) > 0
28
+ end
29
+ end
30
+ end
31
+
32
+ def calc_index(r)
33
+ 2**strategy_class.valid_roles.index(r.to_sym)
34
+ end
35
+ end
36
+
37
+ module Implementation
38
+ class Roles < ::Set # :nodoc:
39
+ attr_reader :model_instance
40
+
41
+ def initialize(sender, *roles)
42
+ super(*roles)
43
+ @model_instance = sender
44
+ end
45
+
46
+ def <<(role)
47
+ model_instance.roles = super.to_a
48
+ self
49
+ end
50
+ end
51
+
52
+ def role_attribute
53
+ strategy_class.roles_attribute_name
54
+ end
55
+
56
+ # assign roles
57
+ def roles=(*roles)
58
+ self.send("#{role_attribute}=", (roles.flatten.map { |r| r.to_sym } & strategy_class.valid_roles).map { |r| calc_index(r) }.inject { |sum, bitvalue| sum + bitvalue })
59
+ end
60
+ alias_method :role=, :roles=
61
+
62
+ # query assigned roles
63
+ def roles
64
+ strategy_class::Roles.new(self, strategy_class.valid_roles.reject { |r| ((self.send(role_attribute) || 0) & calc_index(r)).zero? })
65
+ end
66
+
67
+ def roles_list
68
+ roles.to_a
69
+ end
70
+
71
+ protected
72
+
73
+ def calc_index(r)
74
+ 2**strategy_class.valid_roles.index(r)
75
+ end
76
+ end
77
+
78
+ extend Roles::Generic::User::Configuration
79
+ configure
80
+ end
81
+ end
@@ -0,0 +1,56 @@
1
+ puts "AF"
2
+
3
+ module RoleStrategy::DataMapper
4
+ module AdminFlag
5
+ def self.default_role_attribute
6
+ :admin_flag
7
+ end
8
+
9
+ def self.included base
10
+ base.extend ClassMethods
11
+ end
12
+
13
+ module ClassMethods
14
+ def role_attribute
15
+ strategy_class.roles_attribute_name.to_sym
16
+ end
17
+
18
+ def in_role(role_name)
19
+ case role_name.downcase.to_sym
20
+ when :admin
21
+ all(role_attribute => :admin)
22
+ else
23
+ all(role_attribute => :default)
24
+ end
25
+ end
26
+ end
27
+
28
+ module Implementation
29
+ def role_attribute
30
+ strategy_class.roles_attribute_name
31
+ end
32
+
33
+ # assign roles
34
+ def roles=(*new_roles)
35
+ first_role = new_roles.flatten.first
36
+ if valid_role?(first_role)
37
+ value = first_role.admin? ? :admin : :default
38
+ self.send("#{role_attribute}=", value)
39
+ else
40
+ raise ArgumentError, "The role #{first_role} is not a valid role"
41
+ end
42
+ end
43
+
44
+ # query assigned roles
45
+ def roles
46
+ role = self.send(role_attribute).include?(:admin) ? strategy_class.admin_role_key : strategy_class.default_role_key
47
+ [role]
48
+ end
49
+ alias_method :roles_list, :roles
50
+
51
+ end # Implementation
52
+
53
+ extend Roles::Generic::User::Configuration
54
+ configure :num => :single
55
+ end
56
+ end
@@ -0,0 +1,62 @@
1
+ class Role
2
+ def self.named role_names
3
+ where(:name.in => role_names.flatten)
4
+ end
5
+
6
+ belongs_to :user, :required => false
7
+ end
8
+
9
+ module RoleStrategy::DataMapper
10
+ module OneRole
11
+ def self.default_role_attribute
12
+ :one_role
13
+ end
14
+
15
+ def self.included base
16
+ base.extend Roles::Generic::Role::ClassMethods
17
+ base.extend ClassMethods
18
+ base.instance_eval "has 1, :one_role, 'Role'" # , :parent_key => [role_id], :child_key => [:id]
19
+ end
20
+
21
+ module ClassMethods
22
+ def role_attribute
23
+ strategy_class.roles_attribute_name.to_sym
24
+ end
25
+
26
+ def in_role(role_name)
27
+ role = Role.all(:name => role_name).first
28
+ all('one_role.id' => role.id)
29
+ end
30
+
31
+ def in_roles(*roles)
32
+ role_ids = Role.all(:name.in => roles.flatten).map{|role| role.id}
33
+ all(:'one_role.id'.in => role_ids)
34
+ end
35
+ end
36
+
37
+ module Implementation
38
+ # assign roles
39
+ def roles=(*roles)
40
+ raise "Role class #{role_class} does not have a #find_role(role) method" if !role_class.respond_to? :find_role
41
+ first_role = roles.flatten.first
42
+ role_relation = role_class.find_role(first_role)
43
+ self.send("#{role_attribute}=", role_relation)
44
+ save
45
+ end
46
+ alias_method :role=, :roles=
47
+
48
+ # query assigned roles
49
+ def roles
50
+ role = self.send(role_attribute).name.to_sym
51
+ [role]
52
+ end
53
+
54
+ def roles_list
55
+ self.roles.to_a
56
+ end
57
+ end
58
+
59
+ extend Roles::Generic::User::Configuration
60
+ configure :num => :single, :type => :role_class
61
+ end
62
+ end
@@ -0,0 +1,51 @@
1
+ module RoleStrategy::DataMapper
2
+ module RoleString
3
+ def self.default_role_attribute
4
+ :role_string
5
+ end
6
+
7
+ def self.included base
8
+ base.extend ClassMethods
9
+ end
10
+
11
+ module ClassMethods
12
+ def role_attribute
13
+ strategy_class.roles_attribute_name.to_sym
14
+ end
15
+
16
+ def in_role role_name
17
+ all(:role_string => role_name)
18
+ end
19
+ end
20
+
21
+
22
+ module Implementation
23
+ def role_attribute
24
+ strategy_class.roles_attribute_name
25
+ end
26
+
27
+ # assign roles
28
+ def roles=(*roles)
29
+ self.role = roles.select_labels.first.to_s
30
+ end
31
+
32
+ def role= role_name
33
+ if role_name.kind_of_label? && valid_role?(role_name)
34
+ self.send("#{role_attribute}=", role_name.to_s)
35
+ end
36
+ end
37
+
38
+ # query assigned roles
39
+ def roles
40
+ role = self.send(role_attribute)
41
+ [role.to_sym]
42
+ end
43
+ alias_method :roles_list, :roles
44
+ end
45
+
46
+ extend Roles::Generic::User::Configuration
47
+ configure :num => :single
48
+ end
49
+ end
50
+
51
+
@@ -0,0 +1,15 @@
1
+ require 'sugar-high/file'
2
+ require 'sugar-high/array'
3
+
4
+ module Roles::Strategy
5
+ class << self
6
+ def role_dir
7
+ File.dirname(__FILE__)
8
+ end
9
+
10
+ def gem_name
11
+ :roles_data_mapper
12
+ end
13
+ end
14
+ end
15
+
@@ -0,0 +1,12 @@
1
+ require 'roles_generic'
2
+ require 'require_all'
3
+ require 'set'
4
+ require 'sugar-high/array'
5
+
6
+ require 'dm-core'
7
+ require 'dm-types'
8
+ require 'dm-migrations'
9
+
10
+ require 'roles_data_mapper/namespaces'
11
+ require 'roles_data_mapper/base'
12
+ require 'roles_data_mapper/strategy'