effective_organizations 0.0.2 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bcbee46f5235da4b9d6fa04d84daab02383cfe373532138dc6ec601fc3110ced
4
- data.tar.gz: a400d6e2ecec13c3a98b6e58beda724471628e9262100dbeb5f9b414940fd417
3
+ metadata.gz: a2ee1cb9ffc7df883ea343966168245ab3d77ba59ef9753a20d825702ba46aaa
4
+ data.tar.gz: fcd8f65d9dbc66c5073077e6bd7fe9f48774c4444d965c7c4ce95d09c3d97935
5
5
  SHA512:
6
- metadata.gz: c7a6df31f4b94032905653c0ba44489ba4ac87b47f7e48e488726e4e9c9d8a26b41a02211f94f277ce91c871765ef0bce77a33ebf4aa0dbaef9a5f71ddf83520
7
- data.tar.gz: 84dfedd0a963e6080faac3e7e8553e7739d9179d9e13d4aabb251516848fae840668d02c627884d6acb78d12588d5a221a3d287ee0d63d9b75f7f4b0389dce30
6
+ metadata.gz: a34485e30e3d66f85cb4dff1ed2ccd6656134ac5171c2ceae64e8fc30336144c1ac6c9889dab98b018dbdad0c2b3bda96e583f70583a9907f09eaf1ed4ebe1a0
7
+ data.tar.gz: fb7e677000619da597b0b43f5ae827211d2d55fca0d51326559b27bb7fc7fbd7b3155260afa37f7768360a0f695d2d80667dabc680414f2479582c645c438dac
data/README.md CHANGED
@@ -71,16 +71,85 @@ Add a link to the admin menu:
71
71
 
72
72
  All authorization checks are handled via the effective_resources gem found in the `config/initializers/effective_resources.rb` file.
73
73
 
74
+ ## Effective Roles
75
+
76
+ This gem works with effective roles for the representative roles.
77
+
78
+ Configure your `config/initializers/effective_roles.rb` something like this:
79
+
80
+ ```
81
+ EffectiveRoles.setup(:caaa) do |config|
82
+ config.roles = [:admin, :reserved, :owner, :billing] # Only add to the end of this array. Never prepend roles.
83
+
84
+ # config.role_descriptions
85
+ # ========================
86
+ # This setting configures the text that is displayed by form helpers (see README.md)
87
+
88
+ config.role_descriptions = {
89
+ 'User' => {
90
+ # User roles
91
+ admin: 'can log in to the /admin section of the website. full access to everything.',
92
+ },
93
+ 'Effective::Representative' => {
94
+ owner: 'the owner. full access to everything.',
95
+ billing: 'the billing contact. full access to everything.'
96
+ }
97
+ }
98
+
99
+ # config.assignable_roles
100
+ # Which roles can be assigned by whom
101
+ # =======================
102
+ # When current_user is passed into a form helper function (see README.md)
103
+ # this setting determines which roles that current_user may assign
104
+ config.assignable_roles = {
105
+ 'User' => { admin: [:admin] },
106
+
107
+ 'Effective::Representative' => {
108
+ admin: [:owner, :billing],
109
+ owner: [:owner, :billing],
110
+ billing: [:billing]
111
+ }
112
+ }
113
+ end
114
+ ```
115
+
116
+
74
117
  ## Permissions
75
118
 
76
119
  The permissions you actually want to define are as follows (using CanCan):
77
120
 
78
121
  ```ruby
122
+ if user.persisted?
123
+ can :index, EffectiveOrganizations.Organization
124
+ can(:show, EffectiveOrganizations.Organization) { |organization| user.organizations.include?(organization) }
125
+
126
+ can([:edit, :update], EffectiveOrganizations.Organization) do |organization|
127
+ rep = user.representative(organization: organization)
128
+ rep && (rep.is?(:owner) || rep.is?(:billing))
129
+ end
130
+
131
+ can :index, Effective::Representative
132
+ can(:new, Effective::Representative)
133
+
134
+ can([:create, :edit, :update], Effective::Representative) do |representative|
135
+ rep = user.representative(organization: representative.organization)
136
+ rep && (rep.is?(:owner) || rep.is?(:billing))
137
+ end
138
+
139
+ can(:destroy, Effective::Representative) do |representative|
140
+ allowed = !(representative.is?(:owner) || representative.is?(:billing))
141
+ rep = user.representative(organization: representative.organization)
142
+
143
+ allowed && rep && (rep.is?(:owner) || rep.is?(:billing))
144
+ end
145
+ end
79
146
 
80
147
  if user.admin?
81
148
  can :admin, :effective_organizations
82
- can :manage, Effective::Organization
83
- can :manage, Effective::Representative
149
+ can(crud, EffectiveOrganizations.Organization)
150
+
151
+ can(crud - [:destroy], Effective::Representative)
152
+ can(:destroy, Effective::Representative) { |rep| !rep.is?(:owner) }
84
153
  end
85
154
  ```
86
155
 
@@ -11,11 +11,24 @@ class EffectiveRepresentativesDatatable < Effective::Datatable
11
11
 
12
12
  col :roles, search: roles_collection
13
13
 
14
- actions_col
14
+ unless attributes[:actions] == false
15
+ actions_col
16
+ end
17
+
15
18
  end
16
19
 
17
20
  collection do
18
- Effective::Representative.deep.all.where(organization: current_user.organizations)
21
+ scope = Effective::Representative.deep.all.where(organization: current_user.organizations)
22
+
23
+ if attributes[:organization_id]
24
+ scope = scope.where(organization_id: attributes[:organization_id])
25
+ end
26
+
27
+ if attributes[:user_id]
28
+ scope = scope.where(user_id: attributes[:user_id])
29
+ end
30
+
31
+ scope
19
32
  end
20
33
 
21
34
  def roles_collection
@@ -6,7 +6,11 @@ module EffectiveOrganizationsOrganization
6
6
  extend ActiveSupport::Concern
7
7
 
8
8
  module Base
9
- def effective_organizations_organization
9
+ def effective_organizations_organization(users_source_type: nil)
10
+ @effective_organizations_organization_opts = {
11
+ users_source_type: users_source_type
12
+ }
13
+
10
14
  include ::EffectiveOrganizationsOrganization
11
15
  end
12
16
  end
@@ -20,7 +24,7 @@ module EffectiveOrganizationsOrganization
20
24
  end
21
25
 
22
26
  included do
23
- log_changes(except: :representatives) if respond_to?(:log_changes)
27
+ log_changes(except: [:representatives, :users]) if respond_to?(:log_changes)
24
28
 
25
29
  # rich_text_body
26
30
  # has_many_rich_texts
@@ -28,7 +32,10 @@ module EffectiveOrganizationsOrganization
28
32
  has_many :representatives, -> { Effective::Representative.sorted },
29
33
  class_name: 'Effective::Representative', inverse_of: :organization, dependent: :delete_all
30
34
 
31
- has_many :users, through: :representatives
35
+ accepts_nested_attributes_for :representatives, allow_destroy: true
36
+
37
+ has_many :users, through: :representatives,
38
+ source_type: (@effective_organizations_organization_opts[:users_source_type] || (name.start_with?('Effective') ? '::User' : "#{name.split('::').first}::Organization"))
32
39
 
33
40
  effective_resource do
34
41
  title :string
@@ -53,4 +60,13 @@ module EffectiveOrganizationsOrganization
53
60
  title.presence || 'New Organization'
54
61
  end
55
62
 
63
+ def representative(user:)
64
+ representatives.find { |rep| rep.user_id == user.id }
65
+ end
66
+
67
+ # Find or build
68
+ def build_representative(user:)
69
+ representative(user: user) || representatives.build(user: user)
70
+ end
71
+
56
72
  end
@@ -6,7 +6,11 @@ module EffectiveOrganizationsUser
6
6
  extend ActiveSupport::Concern
7
7
 
8
8
  module Base
9
- def effective_organizations_user
9
+ def effective_organizations_user(organizations_source_type: nil)
10
+ @effective_organizations_user_opts = {
11
+ organizations_source_type: organizations_source_type
12
+ }
13
+
10
14
  include ::EffectiveOrganizationsUser
11
15
  end
12
16
  end
@@ -20,8 +24,11 @@ module EffectiveOrganizationsUser
20
24
  has_many :representatives, -> { Effective::Representative.sorted },
21
25
  class_name: 'Effective::Representative', inverse_of: :user, dependent: :delete_all
22
26
 
27
+ accepts_nested_attributes_for :representatives, allow_destroy: true
28
+
23
29
  # App scoped
24
- has_many :organizations, through: :representatives
30
+ has_many :organizations, through: :representatives,
31
+ source_type: @effective_organizations_user_opts[:organizations_source_type] || "#{name.split('::').first}::Organization"
25
32
  end
26
33
 
27
34
  def representative(organization:)
@@ -3,5 +3,6 @@ module Effective
3
3
  self.table_name = EffectiveOrganizations.organizations_table_name.to_s
4
4
 
5
5
  effective_organizations_organization
6
+
6
7
  end
7
8
  end
@@ -7,9 +7,10 @@ module Effective
7
7
 
8
8
  log_changes(to: :organization) if respond_to?(:log_changes)
9
9
 
10
- belongs_to :organization, counter_cache: true
10
+ belongs_to :organization, polymorphic: true, counter_cache: true
11
11
  belongs_to :user, polymorphic: true
12
12
 
13
+ accepts_nested_attributes_for :organization
13
14
  accepts_nested_attributes_for :user
14
15
 
15
16
  effective_resource do
@@ -28,8 +29,8 @@ module Effective
28
29
  validates :organization, presence: true
29
30
  validates :user, presence: true
30
31
 
31
- validates :user_id, if: -> { user_id && user_type && organization_id },
32
- uniqueness: { scope: [:organization_id], message: 'already belongs to this organization' }
32
+ validates :user_id, if: -> { user_id && user_type && organization_id && organization_type },
33
+ uniqueness: { scope: [:organization_id, :organization_type], message: 'already belongs to this organization' }
33
34
 
34
35
  def to_s
35
36
  user.to_s
@@ -40,5 +41,10 @@ module Effective
40
41
  self.user = user_type.constantize.new(attributes)
41
42
  end
42
43
 
44
+ def build_organization(attributes = {})
45
+ raise('please assign organization_type first') if organization_type.blank?
46
+ self.organization = organization_type.constantize.new(attributes)
47
+ end
48
+
43
49
  end
44
50
  end
@@ -0,0 +1,6 @@
1
+ - categories = EffectiveOrganizations.Organization.categories
2
+
3
+ - if categories.present?
4
+ = f.select :category, categories, required: true
5
+
6
+ = f.text_field :title
@@ -1,14 +1,9 @@
1
1
  = effective_form_with(model: [:admin, organization], engine: true) do |f|
2
- - categories = EffectiveOrganizations.Organization.categories
3
-
4
- - if categories.present?
5
- = f.select :category, categories, required: true
6
-
7
- = f.text_field :title
2
+ = render 'admin/organizations/fields', f: f
8
3
 
9
4
  = effective_submit(f)
10
5
 
11
6
  - if organization.persisted?
12
7
  %h2 Representatives
13
- - datatable = Admin::EffectiveRepresentativesDatatable.new(organization_id: organization.id)
8
+ - datatable = Admin::EffectiveRepresentativesDatatable.new(organization_id: organization.id, organization_type: organization.class.name)
14
9
  = render_inline_datatable(datatable)
@@ -4,12 +4,13 @@
4
4
  = f.hidden_field :user_id
5
5
  = f.hidden_field :user_type
6
6
  = f.hidden_field :organization_id
7
+ = f.hidden_field :organization_type
7
8
 
8
9
  - if f.object.new_record?
9
10
  - unless inline_datatable? && inline_datatable.attributes[:organization_id].present?
10
- = f.select :organization_id, EffectiveOrganizations.Organization.sorted
11
+ = f.select :organization, { 'Organizations' => EffectiveOrganizations.Organization.sorted }, polymorphic: true
11
12
 
12
- = f.checks :roles, EffectiveRoles.roles_collection(f.object)
13
+ = f.checks :roles, EffectiveRoles.roles_collection(f.object, skip_disabled: true)
13
14
 
14
15
  - unless inline_datatable? && inline_datatable.attributes[:user_id].present?
15
16
  = f.radios :new_representative_user_action, ['Invite new user', 'Add existing user'], inline: true, label: 'Representative'
@@ -28,7 +29,7 @@
28
29
  - unless inline_datatable? && inline_datatable.attributes[:user_id].present?
29
30
  = f.static_field :user
30
31
 
31
- = f.checks :roles, EffectiveRoles.roles_collection(f.object)
32
+ = f.checks :roles, EffectiveRoles.roles_collection(f.object, skip_disabled: true)
32
33
 
33
34
  - unless inline_datatable? && inline_datatable.attributes[:user_id].present?
34
35
  = f.fields_for :user, f.object.user do |fu|
@@ -0,0 +1,6 @@
1
+ - categories = EffectiveOrganizations.Organization.categories
2
+
3
+ - if categories.present?
4
+ = f.select :category, categories, required: true
5
+
6
+ = f.text_field :title
@@ -1,16 +1,11 @@
1
1
  - url = (organization.persisted? ? effective_organizations.organization_path(organization) : effective_organizations.organizations_path)
2
2
 
3
3
  = effective_form_with(model: organization, url: url) do |f|
4
- - categories = EffectiveOrganizations.Organization.categories
5
-
6
- - if categories.present?
7
- = f.select :category, categories, required: true
8
-
9
- = f.text_field :title
4
+ = render 'effective/organizations/fields', f: f
10
5
 
11
6
  = f.submit
12
7
 
13
8
  - if organization.persisted?
14
9
  %h2 Representatives
15
- - datatable = EffectiveRepresentativesDatatable.new(organization_id: organization.id)
10
+ - datatable = EffectiveRepresentativesDatatable.new(organization: organization)
16
11
  = render_inline_datatable(datatable)
@@ -4,12 +4,13 @@
4
4
  = f.hidden_field :user_id
5
5
  = f.hidden_field :user_type
6
6
  = f.hidden_field :organization_id
7
+ = f.hidden_field :organization_type
7
8
 
8
9
  - if f.object.new_record?
9
10
  - unless inline_datatable? && inline_datatable.attributes[:organization_id].present?
10
- = f.select :organization_id, EffectiveOrganizations.Organization.sorted
11
+ = f.select :organization, { 'Organizations' => EffectiveOrganizations.Organization.sorted }, polymorphic: true
11
12
 
12
- = f.checks :roles, EffectiveRoles.roles_collection(f.object)
13
+ = f.checks :roles, EffectiveRoles.roles_collection(f.object, skip_disabled: true)
13
14
 
14
15
  - unless inline_datatable? && inline_datatable.attributes[:user_id].present?
15
16
  = f.hidden_field :new_representative_user_action, value: 'Invite new user'
@@ -24,7 +25,7 @@
24
25
  - unless inline_datatable? && inline_datatable.attributes[:user_id].present?
25
26
  = f.static_field :user
26
27
 
27
- = f.checks :roles, EffectiveRoles.roles_collection(f.object)
28
+ = f.checks :roles, EffectiveRoles.roles_collection(f.object, skip_disabled: true)
28
29
 
29
30
  = f.fields_for :user, f.object.user do |fu|
30
31
  = render 'effective/representatives/user_fields', f: fu
@@ -18,7 +18,6 @@ class CreateEffectiveOrganizations < ActiveRecord::Migration[6.0]
18
18
  # Representatives
19
19
  create_table :representatives do |t|
20
20
  t.integer :organization_id
21
- t.string :organization_type
22
21
 
23
22
  t.integer :user_id
24
23
  t.string :user_type
@@ -29,7 +28,7 @@ class CreateEffectiveOrganizations < ActiveRecord::Migration[6.0]
29
28
  t.datetime :created_at
30
29
  end
31
30
 
32
- add_index :representatives, [:organization_id, :organization_type]
31
+ add_index :representatives, [:organization_id]
33
32
  add_index :representatives, [:user_id, :user_type]
34
33
 
35
34
  end
@@ -1,3 +1,3 @@
1
1
  module EffectiveOrganizations
2
- VERSION = '0.0.2'.freeze
2
+ VERSION = '0.0.6'.freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: effective_organizations
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Code and Effect
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-12-10 00:00:00.000000000 Z
11
+ date: 2021-12-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -66,6 +66,20 @@ dependencies:
66
66
  - - ">="
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: effective_roles
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
69
83
  - !ruby/object:Gem::Dependency
70
84
  name: sqlite3
71
85
  requirement: !ruby/object:Gem::Requirement
@@ -178,11 +192,13 @@ files:
178
192
  - app/models/concerns/effective_organizations_user.rb
179
193
  - app/models/effective/organization.rb
180
194
  - app/models/effective/representative.rb
195
+ - app/views/admin/organizations/_fields.html.haml
181
196
  - app/views/admin/organizations/_form.html.haml
182
197
  - app/views/admin/organizations/_form_organization.html.haml
183
198
  - app/views/admin/representatives/_form.html.haml
184
199
  - app/views/admin/representatives/_user_fields.html.haml
185
200
  - app/views/effective/organizations/_dashboard.html.haml
201
+ - app/views/effective/organizations/_fields.html.haml
186
202
  - app/views/effective/organizations/_form.html.haml
187
203
  - app/views/effective/organizations/_form_organization.html.haml
188
204
  - app/views/effective/representatives/_form.html.haml