Class: LcpRuby::Groups::ModelLoader

Inherits:
Object
  • Object
show all
Includes:
Contract
Defined in:
lib/lcp_ruby/groups/model_loader.rb

Instance Method Summary collapse

Instance Method Details

#all_group_namesArray<String>

Returns all active group names from the DB.

Returns:

  • (Array<String>)


8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# File 'lib/lcp_ruby/groups/model_loader.rb', line 8

def all_group_names
  config = LcpRuby.configuration
  model_class = LcpRuby.registry.model_for(config.group_model)
  fields = config.group_model_fields.transform_keys(&:to_s)

  name_field = require_field!(fields, "name", "group_model_fields")
  active_field = fields["active"]

  scope = model_class.all
  if active_field && model_class.column_names.include?(active_field.to_s)
    scope = scope.where(active_field => true)
  end

  scope.pluck(name_field).map(&:to_s).sort
rescue LcpRuby::Error, ActiveRecord::StatementInvalid => e
  log_warn("Failed to load group names: #{e.message}")
  []
end

#groups_for_user(user) ⇒ Array<String>

Returns group names the user belongs to via the membership table.

Parameters:

  • user (Object)

Returns:

  • (Array<String>)


30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/lcp_ruby/groups/model_loader.rb', line 30

def groups_for_user(user)
  return [] unless user

  config = LcpRuby.configuration
  group_class = LcpRuby.registry.model_for(config.group_model)
  membership_class = LcpRuby.registry.model_for(config.group_membership_model)

  group_fields = config.group_model_fields.transform_keys(&:to_s)
  membership_fields = config.group_membership_fields.transform_keys(&:to_s)

  name_field = require_field!(group_fields, "name", "group_model_fields")
  active_field = group_fields["active"]
  group_fk = require_field!(membership_fields, "group", "group_membership_fields")
  user_fk = require_field!(membership_fields, "user", "group_membership_fields")

  conn = group_class.connection
  qgfk = conn.quote_column_name(group_fk)
  gpk = conn.quote_column_name(group_class.primary_key)

  scope = group_class
    .joins("INNER JOIN #{membership_class.table_name} ON #{membership_class.table_name}.#{qgfk} = #{group_class.table_name}.#{gpk}")
    .where(membership_class.table_name => { user_fk => user.id })

  if active_field && group_class.column_names.include?(active_field.to_s)
    scope = scope.where(active_field => true)
  end

  scope.pluck(name_field).map(&:to_s)
rescue LcpRuby::Error, ActiveRecord::StatementInvalid => e
  log_warn("Failed to load groups for user ##{user&.id}: #{e.message}")
  []
end

#roles_for_group(group_name) ⇒ Array<String>

Returns role names mapped to the given group via the mapping table. Returns [] when group_role_mapping_model is nil (membership-only mode).

Parameters:

  • group_name (String)

Returns:

  • (Array<String>)


67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/lcp_ruby/groups/model_loader.rb', line 67

def roles_for_group(group_name)
  config = LcpRuby.configuration
  return [] unless config.group_role_mapping_model

  group_class = LcpRuby.registry.model_for(config.group_model)
  mapping_class = LcpRuby.registry.model_for(config.group_role_mapping_model)

  group_fields = config.group_model_fields.transform_keys(&:to_s)
  mapping_fields = config.group_role_mapping_fields.transform_keys(&:to_s)

  name_field = require_field!(group_fields, "name", "group_model_fields")
  mapping_group_fk = require_field!(mapping_fields, "group", "group_role_mapping_fields")
  role_field = require_field!(mapping_fields, "role", "group_role_mapping_fields")

  group_record = group_class.find_by(name_field => group_name)
  return [] unless group_record

  mapping_class.where(mapping_group_fk => group_record.id).pluck(role_field).map(&:to_s)
rescue LcpRuby::Error, ActiveRecord::StatementInvalid => e
  log_warn("Failed to load roles for group '#{group_name}': #{e.message}")
  []
end

#roles_for_user(user) ⇒ Array<String>

Optimized: returns all roles derived from a user’s group memberships via a single query joining groups, memberships, and mappings.

Parameters:

  • user (Object)

Returns:

  • (Array<String>)


118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
# File 'lib/lcp_ruby/groups/model_loader.rb', line 118

def roles_for_user(user)
  config = LcpRuby.configuration
  return [] unless user
  return [] unless config.group_role_mapping_model

  group_class = LcpRuby.registry.model_for(config.group_model)
  membership_class = LcpRuby.registry.model_for(config.group_membership_model)
  mapping_class = LcpRuby.registry.model_for(config.group_role_mapping_model)

  group_fields = config.group_model_fields.transform_keys(&:to_s)
  membership_fields = config.group_membership_fields.transform_keys(&:to_s)
  mapping_fields = config.group_role_mapping_fields.transform_keys(&:to_s)

  active_field = group_fields["active"]
  membership_group_fk = require_field!(membership_fields, "group", "group_membership_fields")
  user_fk = require_field!(membership_fields, "user", "group_membership_fields")
  mapping_group_fk = require_field!(mapping_fields, "group", "group_role_mapping_fields")
  role_field = require_field!(mapping_fields, "role", "group_role_mapping_fields")

  gt = group_class.table_name
  mt = membership_class.table_name
  mpt = mapping_class.table_name
  conn = mapping_class.connection
  gpk = conn.quote_column_name(group_class.primary_key)
  qmgfk = conn.quote_column_name(mapping_group_fk)
  qmbgfk = conn.quote_column_name(membership_group_fk)

  scope = mapping_class
    .joins("INNER JOIN #{gt} ON #{gt}.#{gpk} = #{mpt}.#{qmgfk}")
    .joins("INNER JOIN #{mt} ON #{mt}.#{qmbgfk} = #{gt}.#{gpk}")
    .where(mt => { user_fk => user.id })

  if active_field && group_class.column_names.include?(active_field.to_s)
    scope = scope.where(gt => { active_field => true })
  end

  scope.distinct.pluck(role_field).map(&:to_s)
rescue LcpRuby::Error, ActiveRecord::StatementInvalid => e
  log_warn("Failed to load roles for user ##{user&.id}: #{e.message}")
  []
end

#user_ids_for_group(group_name) ⇒ Array<Integer>

Returns user IDs that belong to the given group via the membership table.

Parameters:

  • group_name (String)

Returns:

  • (Array<Integer>)


93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/lcp_ruby/groups/model_loader.rb', line 93

def user_ids_for_group(group_name)
  config = LcpRuby.configuration
  group_class = LcpRuby.registry.model_for(config.group_model)
  membership_class = LcpRuby.registry.model_for(config.group_membership_model)

  group_fields = config.group_model_fields.transform_keys(&:to_s)
  membership_fields = config.group_membership_fields.transform_keys(&:to_s)

  name_field = require_field!(group_fields, "name", "group_model_fields")
  group_fk = require_field!(membership_fields, "group", "group_membership_fields")
  user_fk = require_field!(membership_fields, "user", "group_membership_fields")

  group_record = group_class.find_by(name_field => group_name.to_s)
  return [] unless group_record

  membership_class.where(group_fk => group_record.id).pluck(user_fk)
rescue LcpRuby::Error, ActiveRecord::StatementInvalid => e
  log_warn("Failed to load user IDs for group '#{group_name}': #{e.message}")
  []
end