redmine_nonproject_modules 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (29) hide show
  1. checksums.yaml +7 -0
  2. data/app/assets/javascripts/redmine_nonproject_modules.js +1 -0
  3. data/app/assets/stylesheets/redmine_nonproject_modules.css +1 -0
  4. data/app/controllers/group_merge_controller.rb +35 -0
  5. data/app/controllers/group_permissions_controller.rb +35 -0
  6. data/app/helpers/group_merge_helper.rb +31 -0
  7. data/app/models/group_merge.rb +88 -0
  8. data/app/models/group_permission.rb +106 -0
  9. data/app/models/group_permissions_setup.rb +20 -0
  10. data/app/views/group_merge/check.html.erb +35 -0
  11. data/app/views/group_merge/index.html.erb +12 -0
  12. data/app/views/group_permissions/_dependencies.html.erb +10 -0
  13. data/app/views/group_permissions/_member_context.html.erb +5 -0
  14. data/app/views/group_permissions/index.html.erb +24 -0
  15. data/app/views/group_permissions/show.html.erb +36 -0
  16. data/config/initializers/000_dependencies.rb +4 -0
  17. data/config/locales/en.yml +10 -0
  18. data/config/locales/pt-BR.yml +12 -0
  19. data/config/routes.rb +6 -0
  20. data/init.rb +34 -0
  21. data/lib/redmine_nonproject_modules.rb +6 -0
  22. data/lib/redmine_nonproject_modules/dispatcher_finder.rb +32 -0
  23. data/lib/redmine_nonproject_modules/patches/controller_patch.rb +29 -0
  24. data/lib/redmine_nonproject_modules/patches/group_patch.rb +24 -0
  25. data/lib/redmine_nonproject_modules/patches/redmine/i18n_patch.rb +29 -0
  26. data/lib/redmine_nonproject_modules/patches/redmine/menu_manager_patch.rb +91 -0
  27. data/lib/redmine_nonproject_modules/patches/user_patch.rb +19 -0
  28. data/lib/redmine_nonproject_modules/version.rb +8 -0
  29. metadata +137 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 5376c3a5a50a27ab5825bf4c0d6c6cadc2d672047808792d8b7b2d5b47118443
4
+ data.tar.gz: b173b20f273e8236950d0ac67641e40b23a88395ad35a7157828a6c29dddc296
5
+ SHA512:
6
+ metadata.gz: 3b78a4ccfc86da2be65496081ad35730be443faec2b2da9a299ceb4ae8a31e89ede3f94a8b16098484fc5be448b7835179a386c8d494a2201e31173d92ab1446
7
+ data.tar.gz: 57bf1adcd605ee92b9d1be876d67c279cee75b90cc49017996c955dd61c81e61a31370958de94db143ac1fdde6b73c2a4152fcc8714aae1edfc90cfb72f1ed47
@@ -0,0 +1 @@
1
+ //= require 'active_scaffold'
@@ -0,0 +1 @@
1
+ @import 'active_scaffold';
@@ -0,0 +1,35 @@
1
+ class GroupMergeController < ApplicationController
2
+ require_permission 'group_merge'
3
+ helper GroupMergeHelper
4
+
5
+ def index
6
+ @group_merge = ::GroupMerge.new(source: ::Group.find(params[:id]))
7
+ build_targets_list
8
+ end
9
+
10
+ def check
11
+ @group_merge = ::GroupMerge.new(check_parameters)
12
+ return if @group_merge.valid?
13
+ build_targets_list
14
+ render :index
15
+ end
16
+
17
+ def confirm
18
+ @group_merge = ::GroupMerge.new(check_parameters)
19
+ @group_merge.save!
20
+ path = GroupPermission.permission?('group_permissions') ? group_permissions_path : root_path
21
+ redirect_to path, notice: t(:notice_successful_update)
22
+ end
23
+
24
+ private
25
+
26
+ def check_parameters
27
+ params[:group_merge].permit(:target_id).merge(source: ::Group.find(params[:id]))
28
+ end
29
+
30
+ def build_targets_list
31
+ @targets_list = Group.where.not(id: @group_merge.source.id).sorted.map do |g|
32
+ [g.to_s, g.id]
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,35 @@
1
+ class GroupPermissionsController < ApplicationController
2
+ require_permission 'group_permissions'
3
+ before_action :set_group, only: [:show, :update]
4
+
5
+ def index
6
+ @groups = Group.sorted
7
+ end
8
+
9
+ def show
10
+ @gps = GroupPermissionsSetup.new(group: @group)
11
+ end
12
+
13
+ def update
14
+ @gps = GroupPermissionsSetup.new(gps_params)
15
+ if @gps.save
16
+ redirect_to group_permission_path(@group), notice: t(:notice_successful_update)
17
+ else
18
+ render :show
19
+ end
20
+ end
21
+
22
+ private
23
+
24
+ def gps_params
25
+ p = { permissions: [], group: @group }
26
+ if params[:group_permissions_setup] && params[:group_permissions_setup][:permissions]
27
+ p[:permissions] = params[:group_permissions_setup][:permissions]
28
+ end
29
+ p
30
+ end
31
+
32
+ def set_group
33
+ @group = Group.find(params[:id])
34
+ end
35
+ end
@@ -0,0 +1,31 @@
1
+ module GroupMergeHelper
2
+ def group_merge_elements_sorted(group_merge)
3
+ r = group_merge.to_merge_elements.map do |x|
4
+ [group_merge_type_element_label(x[0]),
5
+ group_merge_element_label(x[0]),
6
+ group_merge_element_class(x)]
7
+ end
8
+ r.sort_by { |x| [x[0], x[1]] }
9
+ end
10
+
11
+ def group_merge_element_class(x)
12
+ "GroupMergeHelper_element_#{x[1]}"
13
+ end
14
+
15
+ def group_merge_type_element_label(element)
16
+ t("label_#{element.class.model_name.param_key}")
17
+ end
18
+
19
+ def group_merge_element_label(element)
20
+ m = "group_merge_#{element.class.model_name.param_key}_element_label"
21
+ respond_to?(m) ? send(m, element) : element.to_s
22
+ end
23
+
24
+ def group_merge_member_element_label(m)
25
+ "#{t(:label_project)}: #{m.project} (#{m.roles.to_a.join(', ')})"
26
+ end
27
+
28
+ def group_merge_group_permission_element_label(gp)
29
+ gp.permission
30
+ end
31
+ end
@@ -0,0 +1,88 @@
1
+ require 'virtus'
2
+
3
+ class GroupMerge
4
+ include ActiveModel::Model
5
+ include Virtus.model
6
+ include ActiveModel::Associations
7
+
8
+ ONLY_ON_TARGET = :only_on_target
9
+ ONLY_ON_SOURCE = :only_on_source
10
+ ON_BOTH = :on_both
11
+
12
+ attribute :source_id, Integer
13
+ attribute :target_id, Integer
14
+ belongs_to :source, class_name: 'Group'
15
+ belongs_to :target, class_name: 'Group'
16
+
17
+ validates :source, presence: true
18
+ validates :target, presence: true
19
+
20
+ def [](attr)
21
+ send(attr)
22
+ end
23
+
24
+ def []=(attr, value)
25
+ send("#{attr}=", value)
26
+ end
27
+
28
+ def to_merge_elements
29
+ (target_elements + source_elements).uniq.map do |x|
30
+ [x[0], element_on_status(x)]
31
+ end
32
+ end
33
+
34
+ def save!
35
+ ActiveRecord::Base.transaction do
36
+ source_new_elements.each { |x| add_element_to_target(x[0], x[1]) }
37
+ source.destroy!
38
+ end
39
+ end
40
+
41
+ def associations_to_merge
42
+ [:users, :memberships, :permissions]
43
+ end
44
+
45
+ private
46
+
47
+ def element_on_status(x)
48
+ return ON_BOTH if target_elements.include?(x) && source_elements.include?(x)
49
+ return ONLY_ON_TARGET if target_elements.include?(x)
50
+ return ONLY_ON_SOURCE if source_elements.include?(x)
51
+ raise "Element is neither on source nor on target: #{x}"
52
+ end
53
+
54
+ def target_elements
55
+ @target_elements ||= elements(:target)
56
+ end
57
+
58
+ def source_elements
59
+ @source_elements ||= elements(:source)
60
+ end
61
+
62
+ def elements(sender)
63
+ associations_to_merge.flat_map do |a|
64
+ send(sender).send(a).map do |e|
65
+ [e, a]
66
+ end
67
+ end
68
+ end
69
+
70
+ def source_new_elements
71
+ source_elements.select do |x|
72
+ !target_elements.include?(x)
73
+ end
74
+ end
75
+
76
+ def add_element_to_target(element, association_name)
77
+ method = "add_#{association_name}_element_to_target"
78
+ if respond_to?(method, true)
79
+ send(method, element)
80
+ else
81
+ target.send(association_name) << element
82
+ end
83
+ end
84
+
85
+ def add_permissions_element_to_target(permission)
86
+ target.add_permission(permission)
87
+ end
88
+ end
@@ -0,0 +1,106 @@
1
+ require 'eac_ruby_utils/simple_cache'
2
+
3
+ class GroupPermission < ActiveRecord::Base
4
+ belongs_to :group
5
+
6
+ validates :group, presence: true
7
+ validates :permission, presence: true, uniqueness: { scope: [:group],
8
+ case_sensitive: false }
9
+
10
+ def permission=(value)
11
+ self[:permission] = Permission.sanitize_key(value)
12
+ end
13
+
14
+ class << self
15
+ def permissions
16
+ permissions_hash.values
17
+ end
18
+
19
+ def add_permission(key, options = {})
20
+ p = Permission.new(key, options)
21
+ permissions_hash[p.key] = p unless permissions_hash.key?(p.key)
22
+ end
23
+
24
+ def permission_description(key)
25
+ permission(key).description
26
+ end
27
+
28
+ def permission?(permission, user = false)
29
+ return permission_by_hash?(permission, user) if permission.is_a?(Hash)
30
+ permission(permission).user_has?(user || User.current)
31
+ end
32
+
33
+ def permission(key)
34
+ key = key.to_s
35
+ return permissions_hash[key] if permissions_hash.key?(key)
36
+ raise "Not found \"#{key}\" in GroupPermission::permissions"
37
+ end
38
+
39
+ private
40
+
41
+ def permissions_hash
42
+ @permissions ||= {}.with_indifferent_access
43
+ end
44
+
45
+ def permission_by_hash?(hash, user)
46
+ raise 'Hasy should have :or parameter' unless hash[:or].present?
47
+ ps = hash[:or].is_a?(Array) ? hash[:or] : [hash[:or]]
48
+ ps.any? { |p| permission?(p, user) }
49
+ end
50
+ end
51
+
52
+ class Permission
53
+ include ::EacRubyUtils::SimpleCache
54
+
55
+ class << self
56
+ def sanitize_key(k)
57
+ k.to_s.downcase
58
+ end
59
+ end
60
+
61
+ attr_reader :key, :dependencies
62
+
63
+ def initialize(key, options)
64
+ @key = self.class.sanitize_key(key)
65
+ @dependencies = (options[:dependencies] || []).map { |k| ::GroupPermission.permission(k) }
66
+ end
67
+
68
+ def description
69
+ I18n.t("permission_#{key}_description")
70
+ end
71
+
72
+ def to_s
73
+ key
74
+ end
75
+
76
+ def user_has?(user)
77
+ return true if user.admin
78
+ GroupPermission.where(group: user_groups(user), permission: depends_recursive.to_a).any?
79
+ end
80
+
81
+ def depends_recursive(visited = Set.new)
82
+ return [] if visited.include?(key)
83
+ r = Set.new([key])
84
+ visited << key
85
+ depends.each do |d|
86
+ r += d.depends_recursive(visited)
87
+ end
88
+ r
89
+ end
90
+
91
+ def <=>(other)
92
+ to_s <=> other.to_s
93
+ end
94
+
95
+ private
96
+
97
+ def user_groups(user)
98
+ return [Group.anonymous] if user.anonymous?
99
+ [Group.anonymous, Group.non_member] + user.groups
100
+ end
101
+
102
+ def depends
103
+ ::GroupPermission.permissions.select { |p| p.dependencies.include?(self) }
104
+ end
105
+ end
106
+ end
@@ -0,0 +1,20 @@
1
+ class GroupPermissionsSetup
2
+ include ActiveModel::Model
3
+
4
+ attr_accessor :group
5
+ attr_writer :permissions
6
+
7
+ def permissions
8
+ @permissions ||= GroupPermission.where(group: group).pluck(:permission)
9
+ end
10
+
11
+ def save
12
+ ActiveRecord::Base.transaction do
13
+ GroupPermission.where(group: group).destroy_all
14
+ permissions.each do |p|
15
+ GroupPermission.create!(group: group, permission: p)
16
+ end
17
+ end
18
+ true
19
+ end
20
+ end
@@ -0,0 +1,35 @@
1
+ <%= stylesheet_link_tag 'group_merge', plugin: 'redmine_nonproject_modules' %>
2
+ <%= title [l(:label_group_permission_plural), group_permission_path],
3
+ [@group_merge.source, group_permission_path(@group_merge.source)],
4
+ t(:merge) %>
5
+ <p>
6
+ <%= t(:group_will_be_removed, group: @group_merge.source) %>
7
+ <br/>
8
+ <%= t(:group_will_receive_elements, group: @group_merge.target) %>
9
+ </p>
10
+ <p>
11
+ <span class="GroupMergeHelper_element_only_on_target">
12
+ <%= t(:only_in_group, group: @group_merge.target) %>
13
+ </span>
14
+ <br/>
15
+ <span class="GroupMergeHelper_element_only_on_source">
16
+ <%= t(:only_in_group, group: @group_merge.source) %>
17
+ </span>
18
+ <br/>
19
+ <span class="GroupMergeHelper_element_on_both">
20
+ <%= t(:in_both_group) %>
21
+ </span>
22
+ </p>
23
+ <ul>
24
+ <% group_merge_elements_sorted(@group_merge).each do |x| %>
25
+ <li class="<%= x[2] %>">
26
+ <strong><%= x[0] %>: </strong><%= x[1] %>
27
+ </li>
28
+ <% end %>
29
+ </ul>
30
+ <%= labelled_form_for @group_merge, url: merge_confirm_group_path(@group_merge.source) do |f| %>
31
+ <p><strong>Confirma a mesclagem?</strong></p>
32
+ <%= f.hidden_field :target_id %>
33
+ <%= submit_tag t(:merge) %>
34
+ <%= link_to t(:button_back), merge_group_path(@group_merge.source) %>
35
+ <% end %>
@@ -0,0 +1,12 @@
1
+ <%= title [l(:label_group_permission_plural), group_permission_path],
2
+ [@group_merge.source, group_permission_path(@group_merge.source)],
3
+ t(:merge) %>
4
+ <%= labelled_form_for @group_merge, url: merge_check_group_path(@group_merge.source) do |f| %>
5
+ <%= error_messages_for 'group_merge' %>
6
+ <div class="box tabular">
7
+ <p>
8
+ <%= f.select :target_id, @targets_list, label: t(:field_target) %>
9
+ </p>
10
+ </div>
11
+ <%= submit_tag t(:merge) %>
12
+ <% end %>
@@ -0,0 +1,10 @@
1
+ <ul>
2
+ <% permission.dependencies.each do |d| %>
3
+ <li>
4
+ <%= d %>
5
+ <% if d.dependencies.any? %>
6
+ <%= render partial: 'dependencies', locals: {permission: d } %>
7
+ <% end %>
8
+ </li>
9
+ <% end %>
10
+ </ul>
@@ -0,0 +1,5 @@
1
+ <% if GroupPermission.permission?('group_merge') %>
2
+ <div class="contextual">
3
+ <%= link_to t(:merge), merge_group_path(group) %>
4
+ </div>
5
+ <% end %>
@@ -0,0 +1,24 @@
1
+ <h2><%= t(:label_group_permission_plural) %></h2>
2
+ <table class="list groups">
3
+ <thead>
4
+ <tr>
5
+ <th><%= t(:field_name) %></th>
6
+ <% if GroupPermission.permission?('group_merge') %>
7
+ <th></th>
8
+ <% end %>
9
+ </tr>
10
+ </thead>
11
+ <tbody>
12
+ <% @groups.each do |g| %>
13
+ <% rowclass = cycle("odd", "even") %>
14
+ <tr class="<%= rowclass %>">
15
+ <td style="text-align: left"><%= link_to g, group_permission_path(g) %></td>
16
+ <% if GroupPermission.permission?('group_merge') %>
17
+ <td class="buttons">
18
+ <%= link_to t(:merge), merge_group_path(g) %>
19
+ </td>
20
+ <% end %>
21
+ </tr>
22
+ <% end %>
23
+ </tbody>
24
+ </table>
@@ -0,0 +1,36 @@
1
+ <%= stylesheet_link_tag 'group_permissions', plugin: 'redmine_nonproject_modules' %>
2
+ <%= render partial: 'member_context', locals: { group: @group } %>
3
+ <%= title [l(:label_group_permission_plural), group_permissions_path], @group.name %>
4
+ <%= form_for(@gps, :url => group_permission_path(@group), :method => :put) do %>
5
+ <table class="list group_permissions_list">
6
+ <thead>
7
+ <tr>
8
+ <th><%= t(:field_id) %></th>
9
+ <th><%= t(:field_dependencies) %></th>
10
+ <th><%= t(:field_description) %></th>
11
+ </tr>
12
+ </thead>
13
+ <tbody>
14
+ <% GroupPermission.permissions.sort.each do |id| %>
15
+ <tr class="<%= cycle("odd", "even") %>">
16
+ <td>
17
+ <%= check_box_tag 'group_permissions_setup[permissions][]', id, @gps.permissions.include?(id.key),
18
+ :id => nil %>
19
+ <%= id %>
20
+ </td>
21
+ <td class="dependencies">
22
+ <% if id.dependencies.any? %>
23
+ <%= render partial: 'dependencies', locals: {permission: id } %>
24
+ <% else %>
25
+ -
26
+ <% end %>
27
+ </td>
28
+ <td>
29
+ <%= GroupPermission.permission_description(id) %>
30
+ </td>
31
+ </tr>
32
+ <% end %>
33
+ </tbody>
34
+ </table>
35
+ <p><%= submit_tag l(:button_change) %></p>
36
+ <% end %>
@@ -0,0 +1,4 @@
1
+ Redmine::Plugin.post_register :redmine_nonproject_modules do
2
+ # Source: https://github.com/esquilo-azul/redmine_plugins_helper
3
+ requires_redmine_plugin(:redmine_plugins_helper, version_or_higher: '0.5.2')
4
+ end
@@ -0,0 +1,10 @@
1
+ en:
2
+ field_target: 'Target'
3
+ group_will_be_removed: 'The group "%{group}" will be removed.'
4
+ in_both_group: In both groups.
5
+ label_group_permission: Group permission
6
+ label_group_permission_plural: Groups / Permissions
7
+ merge: Merge
8
+ group_will_receive_elements: 'The group "%{group}" will receive the following elements:'
9
+ only_in_group: 'Only in "%{group}".'
10
+ permission_group_permissions_description: Read/write access to groups' permissions.
@@ -0,0 +1,12 @@
1
+ pt-BR:
2
+ field_target: 'Alvo'
3
+ field_dependencies: Dependências
4
+ group_will_be_removed: 'O grupo "%{group}" será removido.'
5
+ in_both_group: Em ambos os grupos.
6
+ label_group_permission: Permissão de grupo
7
+ label_group_permission_plural: Grupos / Permissões
8
+ merge: Mesclar
9
+ group_will_receive_elements: 'O grupo "%{group}" receberá os seguintes elementos:'
10
+ only_in_group: 'Somente em "%{group}".'
11
+ permission_group_permissions_description: Visualização/modificação das
12
+ permissões de grupo.
@@ -0,0 +1,6 @@
1
+ RedmineApp::Application.routes.draw do
2
+ resources(:group_permissions, only: [:index, :show, :update])
3
+ get '/group/:id/merge', to: 'group_merge#index', as: :merge_group
4
+ post '/group/:id/merge_check', to: 'group_merge#check', as: :merge_check_group
5
+ post '/group/:id/merge_confirm', to: 'group_merge#confirm', as: :merge_confirm_group
6
+ end
data/init.rb ADDED
@@ -0,0 +1,34 @@
1
+ # coding: utf-8
2
+
3
+ require 'active_scaffold'
4
+
5
+ require 'redmine'
6
+
7
+ require 'redmine_nonproject_modules/patches/controller_patch'
8
+ require 'redmine_nonproject_modules/patches/group_patch'
9
+ require 'redmine_nonproject_modules/patches/redmine/i18n_patch'
10
+ require 'redmine_nonproject_modules/patches/redmine/menu_manager_patch'
11
+ require 'redmine_nonproject_modules/version'
12
+
13
+ Redmine::Plugin.register :redmine_nonproject_modules do
14
+ name 'Redmine non-project modules'
15
+ author ::RedmineNonprojectModules::AUTHOR
16
+ description ::RedmineNonprojectModules::SUMMARY
17
+ version ::RedmineNonprojectModules::VERSION
18
+ url ::RedmineNonprojectModules::HOMEPAGE
19
+ author_url 'https://github.com/eduardobogoni'
20
+
21
+ Redmine::MenuManager.map :admin_menu do |menu|
22
+ menu.push :group_permissions, { controller: 'group_permissions', action: 'index' },
23
+ caption: :label_group_permission_plural, after: :groups,
24
+ if: proc { GroupPermission.permission?('group_permissions') }
25
+ end
26
+
27
+ ActiveScaffold.delayed_setup = true
28
+ end
29
+
30
+ Rails.configuration.to_prepare do
31
+ GroupPermission.add_permission('group_permissions')
32
+ GroupPermission.add_permission('group_merge')
33
+ require_dependency 'redmine_nonproject_modules/patches/user_patch'
34
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_scaffold'
4
+
5
+ module RedmineNonprojectModules
6
+ end
@@ -0,0 +1,32 @@
1
+ require 'eac_ruby_utils/simple_cache'
2
+
3
+ module RedmineNonprojectModules
4
+ # https://stackoverflow.com/questions/12088025/detect-if-application-was-started-as...
5
+ # https://github.com/newrelic/rpm/blob/master/lib/new_relic/local_environment.rb
6
+ class DispatcherFinder
7
+ WEBSERVER_DISPATCHERS = %w(webrick passenger).freeze
8
+ DISPATCHERS = WEBSERVER_DISPATCHERS
9
+
10
+ class << self
11
+ include ::EacRubyUtils::SimpleCache
12
+
13
+ def webserver?
14
+ WEBSERVER_DISPATCHERS.include?(dispatcher)
15
+ end
16
+
17
+ def webrick?
18
+ defined?(::WEBrick) && defined?(::WEBrick::VERSION)
19
+ end
20
+
21
+ def passenger?
22
+ defined?(::PhusionPassenger)
23
+ end
24
+
25
+ private
26
+
27
+ def dispatcher_uncached
28
+ DISPATCHERS.find { |d| send("#{d}?") }
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,29 @@
1
+ module RedmineNonprojectModules
2
+ module Patches
3
+ module ControllerPatch
4
+ def self.included(base)
5
+ base.send(:extend, ClassMethods)
6
+ base.send(:include, InstanceMethods)
7
+ end
8
+
9
+ module ClassMethods
10
+ def require_permission(permission)
11
+ before_action { |c| c.before_action_require_permission(permission) }
12
+ end
13
+ end
14
+
15
+ module InstanceMethods
16
+ def before_action_require_permission(permission)
17
+ return true if GroupPermission.permission?(permission)
18
+ deny_access
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+
25
+ unless ActionController::Base.included_modules.include?(
26
+ RedmineNonprojectModules::Patches::ControllerPatch
27
+ )
28
+ ActionController::Base.send(:include, RedmineNonprojectModules::Patches::ControllerPatch)
29
+ end
@@ -0,0 +1,24 @@
1
+ module RedmineNonprojectModules
2
+ module Patches
3
+ module GroupPatch
4
+ def self.included(base)
5
+ base.class_eval do
6
+ has_many :permissions, class_name: 'GroupPermission', dependent: :destroy
7
+ end
8
+ base.include(InstanceMethods)
9
+ end
10
+
11
+ module InstanceMethods
12
+ def add_permission(permission)
13
+ permission = permission.permission if permission.is_a?(::GroupPermission)
14
+ return if permissions.pluck(:permission).include?(permission)
15
+ ::GroupPermission.create!(group: self, permission: permission)
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+
22
+ unless ::Group.included_modules.include?(RedmineNonprojectModules::Patches::GroupPatch)
23
+ ::Group.send(:include, RedmineNonprojectModules::Patches::GroupPatch)
24
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RedmineNonprojectModules
4
+ module Patches
5
+ module Redmine
6
+ module I18nPatch
7
+ def self.included(base)
8
+ base.include(InstanceMethods)
9
+ base.alias_method_chain :l, :active_scaffold
10
+ end
11
+
12
+ module InstanceMethods
13
+ def l_with_active_scaffold(*args)
14
+ if (args.first.is_a?(Time) || args.first.is_a?(Date)) && args.last.is_a?(Hash)
15
+ ::I18n.l(args.first, args.last)
16
+ else
17
+ l_without_active_scaffold(*args)
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+
26
+ x = ::Redmine::I18n
27
+ y = ::RedmineNonprojectModules::Patches::Redmine::I18nPatch
28
+
29
+ x.send(:include, y) unless x.included_modules.include?(y)
@@ -0,0 +1,91 @@
1
+ module RedmineNonprojectModules
2
+ module Patches
3
+ module Redmine
4
+ module MenuManagerMapperPatch
5
+ def self.included(base)
6
+ base.send(:include, InstanceMethods)
7
+ end
8
+ end
9
+
10
+ module InstanceMethods
11
+ def push_controller(*args)
12
+ e = ControllerEntry.new(*args)
13
+ push(*e.build)
14
+ e.permissions.each do |p|
15
+ ::GroupPermission.add_permission(p)
16
+ end
17
+ end
18
+ end
19
+
20
+ class ControllerEntry
21
+ def initialize(controller, options = {})
22
+ @controller = controller.to_s
23
+ @options = options.with_indifferent_access
24
+ end
25
+
26
+ def build
27
+ [build_name, build_url, build_options]
28
+ end
29
+
30
+ def permissions
31
+ parse_permissions(permissions_const)
32
+ end
33
+
34
+ private
35
+
36
+ attr_reader :controller, :options
37
+
38
+ def build_name
39
+ r = controller
40
+ r = "#{r}_#{action}" unless action == 'index'
41
+ r.to_sym
42
+ end
43
+
44
+ def build_url
45
+ { controller: controller, action: action, id: id }
46
+ end
47
+
48
+ def build_options
49
+ {
50
+ caption: build_caption,
51
+ if: proc { GroupPermission.permission?(permissions_const) }
52
+ }
53
+ end
54
+
55
+ def build_caption
56
+ "label_#{build_name}".to_sym
57
+ end
58
+
59
+ def controller_class
60
+ Object.const_get("#{controller.camelize}Controller")
61
+ end
62
+
63
+ def action
64
+ @options[:action] || 'index'
65
+ end
66
+
67
+ def id
68
+ @options[:id]
69
+ end
70
+
71
+ def permissions_const
72
+ controller_class.const_get('PERMISSIONS')
73
+ end
74
+
75
+ def parse_permissions(p)
76
+ return parse_permissions(p.values) if p.is_a?(Hash)
77
+ return p.flat_map { |v| parse_permissions(v) } if p.is_a?(Enumerable)
78
+ [p.to_s]
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end
84
+
85
+ unless ::Redmine::MenuManager::Mapper.included_modules.include?(
86
+ ::RedmineNonprojectModules::Patches::Redmine::MenuManagerMapperPatch
87
+ )
88
+ ::Redmine::MenuManager::Mapper.send(
89
+ :include, ::RedmineNonprojectModules::Patches::Redmine::MenuManagerMapperPatch
90
+ )
91
+ end
@@ -0,0 +1,19 @@
1
+ module RedmineNonprojectModules
2
+ module Patches
3
+ module UserPatch
4
+ def self.included(base)
5
+ base.include(InstanceMethods)
6
+ end
7
+
8
+ module InstanceMethods
9
+ def permission?(permissions)
10
+ GroupPermission.permission?(permissions, self)
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
16
+
17
+ unless ::User.included_modules.include?(RedmineNonprojectModules::Patches::UserPatch)
18
+ ::User.send(:include, RedmineNonprojectModules::Patches::UserPatch)
19
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RedmineNonprojectModules
4
+ AUTHOR = 'Eduardo Henrique Bogoni'
5
+ HOMEPAGE = 'https://github.com/esquilo-azul/redmine_nonproject_modules'
6
+ SUMMARY = 'Support to non-project modules.'
7
+ VERSION = '0.2.1'
8
+ end
metadata ADDED
@@ -0,0 +1,137 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: redmine_nonproject_modules
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.1
5
+ platform: ruby
6
+ authors:
7
+ - 0.2.1
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2019-08-26 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: active_scaffold
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '3.5'
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 3.5.4
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: '3.5'
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 3.5.4
33
+ - !ruby/object:Gem::Dependency
34
+ name: activemodel-associations
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: '0'
40
+ type: :runtime
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: '0'
47
+ - !ruby/object:Gem::Dependency
48
+ name: eac_ruby_utils
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '0.10'
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: 0.10.1
57
+ type: :runtime
58
+ prerelease: false
59
+ version_requirements: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - "~>"
62
+ - !ruby/object:Gem::Version
63
+ version: '0.10'
64
+ - - ">="
65
+ - !ruby/object:Gem::Version
66
+ version: 0.10.1
67
+ - !ruby/object:Gem::Dependency
68
+ name: virtus
69
+ requirement: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ version: '0'
74
+ type: :runtime
75
+ prerelease: false
76
+ version_requirements: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - ">="
79
+ - !ruby/object:Gem::Version
80
+ version: '0'
81
+ description:
82
+ email:
83
+ executables: []
84
+ extensions: []
85
+ extra_rdoc_files: []
86
+ files:
87
+ - app/assets/javascripts/redmine_nonproject_modules.js
88
+ - app/assets/stylesheets/redmine_nonproject_modules.css
89
+ - app/controllers/group_merge_controller.rb
90
+ - app/controllers/group_permissions_controller.rb
91
+ - app/helpers/group_merge_helper.rb
92
+ - app/models/group_merge.rb
93
+ - app/models/group_permission.rb
94
+ - app/models/group_permissions_setup.rb
95
+ - app/views/group_merge/check.html.erb
96
+ - app/views/group_merge/index.html.erb
97
+ - app/views/group_permissions/_dependencies.html.erb
98
+ - app/views/group_permissions/_member_context.html.erb
99
+ - app/views/group_permissions/index.html.erb
100
+ - app/views/group_permissions/show.html.erb
101
+ - config/initializers/000_dependencies.rb
102
+ - config/locales/en.yml
103
+ - config/locales/pt-BR.yml
104
+ - config/routes.rb
105
+ - init.rb
106
+ - lib/redmine_nonproject_modules.rb
107
+ - lib/redmine_nonproject_modules/dispatcher_finder.rb
108
+ - lib/redmine_nonproject_modules/patches/controller_patch.rb
109
+ - lib/redmine_nonproject_modules/patches/group_patch.rb
110
+ - lib/redmine_nonproject_modules/patches/redmine/i18n_patch.rb
111
+ - lib/redmine_nonproject_modules/patches/redmine/menu_manager_patch.rb
112
+ - lib/redmine_nonproject_modules/patches/user_patch.rb
113
+ - lib/redmine_nonproject_modules/version.rb
114
+ homepage: https://github.com/esquilo-azul/redmine_nonproject_modules
115
+ licenses: []
116
+ metadata: {}
117
+ post_install_message:
118
+ rdoc_options: []
119
+ require_paths:
120
+ - lib
121
+ required_ruby_version: !ruby/object:Gem::Requirement
122
+ requirements:
123
+ - - ">="
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ required_rubygems_version: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - ">="
129
+ - !ruby/object:Gem::Version
130
+ version: '0'
131
+ requirements: []
132
+ rubyforge_project:
133
+ rubygems_version: 2.7.7
134
+ signing_key:
135
+ specification_version: 4
136
+ summary: Support to non-project modules.
137
+ test_files: []