decidim-admin 0.11.2 → 0.12.0.pre

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of decidim-admin might be problematic. Click here for more details.

Files changed (116) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/decidim/admin/application.js.es6 +5 -1
  3. data/app/assets/javascripts/decidim/admin/bundle.js +47 -0
  4. data/app/assets/javascripts/decidim/admin/bundle.js.map +1 -0
  5. data/app/assets/javascripts/decidim/admin/component_permissions.js.es6 +13 -0
  6. data/app/assets/javascripts/decidim/admin/managed_users.js.es6 +2 -1
  7. data/app/assets/javascripts/decidim/admin/subform_toggler.component.js.es6 +14 -7
  8. data/app/assets/stylesheets/decidim/admin/_decidim.scss +2 -0
  9. data/app/assets/stylesheets/decidim/admin/bundle.scss +1 -0
  10. data/app/assets/stylesheets/decidim/admin/components/_autocomplete_select.component.scss +13 -0
  11. data/app/assets/stylesheets/decidim/admin/modules/_secondary-nav.scss +3 -2
  12. data/app/assets/stylesheets/decidim/admin/modules/_table-list.scss +7 -0
  13. data/app/commands/decidim/admin/create_static_page.rb +7 -1
  14. data/app/commands/decidim/admin/update_component_permissions.rb +9 -3
  15. data/app/commands/decidim/admin/update_organization_tos_version.rb +47 -0
  16. data/app/commands/decidim/admin/update_static_page.rb +5 -0
  17. data/app/constraints/decidim/admin/organization_dashboard_constraint.rb +6 -3
  18. data/app/controllers/concerns/decidim/admin/participatory_space_admin_context.rb +2 -2
  19. data/app/controllers/decidim/admin/application_controller.rb +14 -5
  20. data/app/controllers/decidim/admin/area_types_controller.rb +6 -6
  21. data/app/controllers/decidim/admin/areas_controller.rb +6 -6
  22. data/app/controllers/decidim/admin/authorization_workflows_controller.rb +1 -1
  23. data/app/controllers/decidim/admin/categories_controller.rb +7 -7
  24. data/app/controllers/decidim/admin/component_permissions_controller.rb +20 -8
  25. data/app/controllers/decidim/admin/components/base_controller.rb +19 -3
  26. data/app/controllers/decidim/admin/components_controller.rb +8 -8
  27. data/app/controllers/decidim/admin/concerns/has_attachment_collections.rb +8 -8
  28. data/app/controllers/decidim/admin/concerns/has_attachments.rb +11 -9
  29. data/app/controllers/decidim/admin/concerns/has_private_users.rb +5 -5
  30. data/app/controllers/decidim/admin/dashboard_controller.rb +4 -2
  31. data/app/controllers/decidim/admin/exports_controller.rb +1 -1
  32. data/app/controllers/decidim/admin/impersonatable_users_controller.rb +7 -1
  33. data/app/controllers/decidim/admin/impersonations_controller.rb +2 -4
  34. data/app/controllers/decidim/admin/logs_controller.rb +4 -2
  35. data/app/controllers/decidim/admin/managed_users/impersonation_logs_controller.rb +0 -2
  36. data/app/controllers/decidim/admin/managed_users/promotions_controller.rb +2 -2
  37. data/app/controllers/decidim/admin/moderations_controller.rb +4 -4
  38. data/app/controllers/decidim/admin/newsletters_controller.rb +9 -9
  39. data/app/controllers/decidim/admin/oauth_applications_controller.rb +7 -7
  40. data/app/controllers/decidim/admin/officializations_controller.rb +4 -5
  41. data/app/controllers/decidim/admin/organization_appearance_controller.rb +2 -2
  42. data/app/controllers/decidim/admin/organization_controller.rb +21 -2
  43. data/app/controllers/decidim/admin/scope_types_controller.rb +6 -6
  44. data/app/controllers/decidim/admin/scopes_controller.rb +7 -7
  45. data/app/controllers/decidim/admin/static_pages_controller.rb +16 -7
  46. data/app/controllers/decidim/admin/user_groups_controller.rb +3 -3
  47. data/app/controllers/decidim/admin/users_controller.rb +5 -5
  48. data/app/forms/decidim/admin/managed_user_promotion_form.rb +1 -1
  49. data/app/forms/decidim/admin/permission_form.rb +12 -15
  50. data/app/forms/decidim/admin/static_page_form.rb +1 -0
  51. data/app/frontend/components/autocomplete.component.test.tsx +19 -0
  52. data/app/frontend/components/autocomplete.component.tsx +169 -0
  53. data/app/frontend/entry.ts +17 -0
  54. data/app/frontend/entry_test.ts +4 -0
  55. data/app/helpers/decidim/admin/application_helper.rb +0 -4
  56. data/app/permissions/decidim/admin/permissions.rb +161 -0
  57. data/app/permissions/decidim/admin/user_manager_permissions.rb +66 -0
  58. data/app/views/decidim/admin/area_types/index.html.erb +8 -4
  59. data/app/views/decidim/admin/areas/index.html.erb +6 -3
  60. data/app/views/decidim/admin/attachment_collections/index.html.erb +3 -3
  61. data/app/views/decidim/admin/attachment_collections/show.html.erb +2 -2
  62. data/app/views/decidim/admin/attachments/index.html.erb +3 -3
  63. data/app/views/decidim/admin/attachments/show.html.erb +2 -2
  64. data/app/views/decidim/admin/categories/index.html.erb +5 -5
  65. data/app/views/decidim/admin/categories/show.html.erb +2 -2
  66. data/app/views/decidim/admin/component_permissions/_options_form.html.erb +14 -0
  67. data/app/views/decidim/admin/component_permissions/edit.html.erb +37 -16
  68. data/app/views/decidim/admin/components/_component.html.erb +6 -4
  69. data/app/views/decidim/admin/components/_form.html.erb +6 -6
  70. data/app/views/decidim/admin/dashboard/show.html.erb +1 -1
  71. data/app/views/decidim/admin/impersonatable_users/index.html.erb +5 -3
  72. data/app/views/decidim/admin/moderations/index.html.erb +2 -2
  73. data/app/views/decidim/admin/newsletters/index.html.erb +5 -3
  74. data/app/views/decidim/admin/newsletters/show.html.erb +1 -1
  75. data/app/views/decidim/admin/oauth_applications/index.html.erb +5 -3
  76. data/app/views/decidim/admin/participatory_space_private_users/index.html.erb +3 -3
  77. data/app/views/decidim/admin/scope_types/index.html.erb +5 -3
  78. data/app/views/decidim/admin/scopes/index.html.erb +4 -4
  79. data/app/views/decidim/admin/static_pages/_form.html.erb +3 -1
  80. data/app/views/decidim/admin/static_pages/_form_notable_changes.html.erb +9 -0
  81. data/app/views/decidim/admin/static_pages/index.html.erb +11 -3
  82. data/app/views/decidim/admin/static_pages/show.html.erb +2 -2
  83. data/app/views/decidim/admin/user_groups/index.html.erb +2 -2
  84. data/app/views/decidim/admin/users/index.html.erb +5 -3
  85. data/app/views/layouts/decidim/admin/_application.html.erb +0 -1
  86. data/app/views/layouts/decidim/admin/_template_top.html.erb +1 -0
  87. data/app/views/layouts/decidim/admin/users.html.erb +4 -4
  88. data/config/locales/ca.yml +8 -0
  89. data/config/locales/en.yml +8 -0
  90. data/config/locales/es.yml +8 -0
  91. data/config/locales/eu.yml +8 -0
  92. data/config/locales/fi.yml +8 -0
  93. data/config/locales/fr.yml +8 -0
  94. data/config/locales/gl.yml +8 -0
  95. data/config/locales/it.yml +8 -0
  96. data/config/locales/nl.yml +8 -0
  97. data/config/locales/pl.yml +8 -0
  98. data/config/locales/pt-BR.yml +8 -0
  99. data/config/locales/pt.yml +8 -0
  100. data/config/locales/ru.yml +11 -3
  101. data/config/locales/sv.yml +8 -0
  102. data/config/locales/uk.yml +8 -0
  103. data/config/routes.rb +5 -1
  104. data/lib/decidim/admin.rb +1 -0
  105. data/lib/decidim/admin/engine.rb +17 -20
  106. data/lib/decidim/admin/form_builder.rb +64 -0
  107. data/lib/decidim/admin/test/manage_component_permissions_examples.rb +92 -15
  108. data/lib/decidim/admin/version.rb +1 -1
  109. metadata +25 -17
  110. data/app/models/decidim/admin/abilities/admin_ability.rb +0 -76
  111. data/app/models/decidim/admin/abilities/base_ability.rb +0 -21
  112. data/app/models/decidim/admin/abilities/participatory_process_admin_ability.rb +0 -58
  113. data/app/models/decidim/admin/abilities/participatory_process_collaborator_ability.rb +0 -19
  114. data/app/models/decidim/admin/abilities/participatory_process_moderator_ability.rb +0 -23
  115. data/app/models/decidim/admin/abilities/user_manager_ability.rb +0 -34
  116. data/app/models/decidim/admin/application_record.rb +0 -11
@@ -8,7 +8,7 @@ module Decidim
8
8
  layout "decidim/admin/users"
9
9
 
10
10
  def index
11
- authorize! :index, UserGroup
11
+ enforce_permission_to :index, :user_group
12
12
  @query = params[:q]
13
13
  @state = params[:state]
14
14
 
@@ -18,7 +18,7 @@ module Decidim
18
18
 
19
19
  def verify
20
20
  @user_group = collection.find(params[:id])
21
- authorize! :verify, @user_group
21
+ enforce_permission_to :verify, :user_group, user_group: @user_group
22
22
 
23
23
  VerifyUserGroup.call(@user_group, current_user) do
24
24
  on(:ok) do
@@ -35,7 +35,7 @@ module Decidim
35
35
 
36
36
  def reject
37
37
  @user_group = collection.find(params[:id])
38
- authorize! :reject, @user_group
38
+ enforce_permission_to :reject, :user_group, user_group: @user_group
39
39
 
40
40
  RejectUserGroup.call(@user_group, current_user) do
41
41
  on(:ok) do
@@ -6,17 +6,17 @@ module Decidim
6
6
  #
7
7
  class UsersController < Decidim::Admin::ApplicationController
8
8
  def index
9
- authorize! :index, :admin_users
9
+ enforce_permission_to :read, :admin_user
10
10
  @users = collection.page(params[:page]).per(15)
11
11
  end
12
12
 
13
13
  def new
14
- authorize! :new, :admin_users
14
+ enforce_permission_to :create, :admin_user
15
15
  @form = form(InviteUserForm).instance
16
16
  end
17
17
 
18
18
  def create
19
- authorize! :new, :admin_users
19
+ enforce_permission_to :create, :admin_user
20
20
 
21
21
  default_params = {
22
22
  organization: current_organization,
@@ -40,7 +40,7 @@ module Decidim
40
40
  end
41
41
 
42
42
  def resend_invitation
43
- authorize! :invite, :admin_users
43
+ enforce_permission_to :invite, :admin_user, user: user
44
44
 
45
45
  InviteUserAgain.call(user, "invite_admin") do
46
46
  on(:ok) do
@@ -56,7 +56,7 @@ module Decidim
56
56
  end
57
57
 
58
58
  def destroy
59
- authorize! :destroy, :admin_users
59
+ enforce_permission_to :destroy, :admin_user, user: user
60
60
 
61
61
  RemoveAdmin.call(user, current_user) do
62
62
  on(:ok) do
@@ -7,7 +7,7 @@ module Decidim
7
7
  class ManagedUserPromotionForm < Form
8
8
  attribute :email, String
9
9
 
10
- validates :email, presence: true
10
+ validates :email, presence: true, 'valid_email_2/email': { disposable: true }
11
11
  end
12
12
  end
13
13
  end
@@ -5,27 +5,24 @@ module Decidim
5
5
  # This form handles permissions for a particular action in the admin panel.
6
6
  class PermissionForm < Form
7
7
  attribute :authorization_handler_name, String
8
- attribute :options, String
8
+ attribute :options, Hash
9
9
 
10
- validate :sanitize
11
- validate :options_is_valid_json
10
+ def manifest
11
+ Decidim::Verifications.find_workflow_manifest(authorization_handler_name)
12
+ end
12
13
 
13
- private
14
+ def options_schema
15
+ @options_schema ||= options_manifest.schema.new(options || {})
16
+ end
14
17
 
15
- def sanitize
16
- self.authorization_handler_name = nil if authorization_handler_name.blank?
17
- self.options = nil if authorization_handler_name.blank?
18
- self.options = nil if options.blank?
18
+ def options_attributes
19
+ options_manifest.attributes
19
20
  end
20
21
 
21
- def options_is_valid_json
22
- return unless options
22
+ private
23
23
 
24
- result = JSON.parse(options)
25
- errors.add(:options, :invalid_json) unless result.is_a?(Hash)
26
- result
27
- rescue JSON::ParserError
28
- errors.add(:options, :invalid_json)
24
+ def options_manifest
25
+ manifest.options
29
26
  end
30
27
  end
31
28
  end
@@ -9,6 +9,7 @@ module Decidim
9
9
  attribute :slug, String
10
10
  translatable_attribute :title, String
11
11
  translatable_attribute :content, String
12
+ attribute :changed_notably, Boolean
12
13
 
13
14
  mimic :static_page
14
15
 
@@ -0,0 +1,19 @@
1
+ import { shallow } from "enzyme";
2
+ import * as React from "react";
3
+
4
+ import Autocomplete from "./autocomplete.component";
5
+
6
+ describe("<Autocomplete />", () => {
7
+ const name = "custom[name]";
8
+ const selected = "";
9
+ const options = Array();
10
+ const placeholder = "Pick a value";
11
+ const noResultsText = "No results found";
12
+ const searchPromptText = "Type to search";
13
+ const searchURL = "/some/url";
14
+
15
+ it("renders a div of Select", () => {
16
+ const wrapper = shallow(<Autocomplete name={name} selected={selected} options={options} noResultsText={noResultsText} placeholder={placeholder} searchPromptText={searchPromptText} searchURL={searchURL} />);
17
+ expect(wrapper.find(".autocomplete-field").exists()).toBeTruthy();
18
+ });
19
+ });
@@ -0,0 +1,169 @@
1
+ import axios, { CancelTokenSource } from "axios";
2
+ import * as React from "react";
3
+
4
+ import {Async as AsyncSelect, ReactAsyncSelectProps} from "react-select";
5
+ import "react-select/scss/default.scss";
6
+
7
+ declare module "react-select" {
8
+ interface ReactAsyncSelectProps<TValue = OptionValues> {
9
+ searchPromptText?: any;
10
+ }
11
+ }
12
+
13
+ export interface AutocompleteProps {
14
+ /**
15
+ * Autoload from search url on initialize
16
+ */
17
+ autoload?: boolean;
18
+ /**
19
+ * The name of the input to be submitted with the form
20
+ */
21
+ name: string;
22
+ /**
23
+ * The value of the actually selected option
24
+ */
25
+ selected: any;
26
+ /**
27
+ * An array objects with the preloded options (needs to include the selected option)
28
+ */
29
+ options: any[];
30
+ /**
31
+ * placeholder displayed when there are no matching search results or a falsy value to hide it
32
+ */
33
+ noResultsText: string;
34
+ /**
35
+ * Field placeholder, displayed when there's no value
36
+ */
37
+ placeholder: string;
38
+ /**
39
+ * Text to prompt for search input
40
+ */
41
+ searchPromptText: string;
42
+ /**
43
+ * The URL where fetch content
44
+ */
45
+ searchURL: string;
46
+ }
47
+
48
+ interface AutocompleteState {
49
+ /**
50
+ * The value of the actually selected option
51
+ */
52
+ selectedOption: any;
53
+ /**
54
+ * An array objects with the preloded options (needs to include the selected option)
55
+ */
56
+ options: any[];
57
+ /**
58
+ * Text to prompt for search input
59
+ */
60
+ searchPromptText: string;
61
+ /**
62
+ * Placeholder displayed when there are no matching search results or a falsy value to hide it
63
+ */
64
+ noResultsText: string;
65
+ }
66
+
67
+ export class Autocomplete extends React.Component<AutocompleteProps, AutocompleteState> {
68
+ public static defaultProps: any = {
69
+ autoload: false
70
+ };
71
+
72
+ private cancelTokenSource: CancelTokenSource;
73
+ private minCharactersToSearch: number = 3;
74
+
75
+ constructor(props: AutocompleteProps) {
76
+ super(props);
77
+
78
+ this.state = {
79
+ options: props.options,
80
+ selectedOption: props.selected,
81
+ searchPromptText: props.searchPromptText,
82
+ noResultsText: props.noResultsText
83
+ };
84
+ }
85
+
86
+ public render(): JSX.Element {
87
+ const { autoload, name, placeholder } = this.props;
88
+ const { selectedOption, options, searchPromptText, noResultsText } = this.state;
89
+
90
+ return (
91
+ <div className="autocomplete-field">
92
+ <AsyncSelect
93
+ cache={false}
94
+ name={name}
95
+ value={selectedOption}
96
+ options={options}
97
+ placeholder={placeholder}
98
+ searchPromptText={searchPromptText}
99
+ noResultsText={noResultsText}
100
+ onChange={this.handleChange}
101
+ onInputChange={this.onInputChange}
102
+ loadOptions={this.loadOptions}
103
+ filterOptions={this.filterOptions}
104
+ autoload={autoload}
105
+ removeSelected={true}
106
+ escapeClearsValue={false}
107
+ onCloseResetsInput={false}
108
+ />
109
+ </div>
110
+ );
111
+ }
112
+
113
+ private handleChange = (selectedOption: any) => {
114
+ this.setState({ selectedOption });
115
+ }
116
+
117
+ private filterOptions = (options: any, filter: any, excludeOptions: any) => {
118
+ // Do no filtering, just return all options because
119
+ // we return a filtered set from server
120
+ return options;
121
+ }
122
+
123
+ private onInputChange = (query: string) => {
124
+ if (query.length < this.minCharactersToSearch) {
125
+ this.setState({ noResultsText: this.props.searchPromptText });
126
+ } else {
127
+ this.setState({ noResultsText: this.props.noResultsText });
128
+ }
129
+ }
130
+
131
+ private loadOptions = (query: string, callback: any) => {
132
+ query = query.toLowerCase();
133
+
134
+ if (this.cancelTokenSource) {
135
+ this.cancelTokenSource.cancel();
136
+ }
137
+
138
+ if (query.length < this.minCharactersToSearch) {
139
+ callback (null, { options: [], complete: false });
140
+ } else {
141
+ this.cancelTokenSource = axios.CancelToken.source();
142
+
143
+ axios.get(this.props.searchURL, {
144
+ cancelToken: this.cancelTokenSource.token,
145
+ headers: {
146
+ Accept: "application/json"
147
+ },
148
+ withCredentials: true,
149
+ params: {
150
+ term: query
151
+ }
152
+ })
153
+ .then((response) => {
154
+ // CAREFUL! Only set complete to true when there are no more options,
155
+ // or more specific queries will not be sent to the server.
156
+ callback (null, { options: response.data, complete: true });
157
+ })
158
+ .catch((error: any) => {
159
+ if (axios.isCancel(error)) {
160
+ // console.log("Request canceled", error.message);
161
+ } else {
162
+ callback (error, { options: [], complete: false });
163
+ }
164
+ });
165
+ }
166
+ }
167
+ }
168
+
169
+ export default Autocomplete;
@@ -0,0 +1,17 @@
1
+ import * as React from "react";
2
+ import * as ReactDOM from "react-dom";
3
+
4
+ import Autocomplete, { AutocompleteProps } from "./components/autocomplete.component";
5
+
6
+ window.DecidimAdmin = window.DecidimAdmin || {};
7
+
8
+ window.DecidimAdmin.renderAutocompleteSelects = (nodeSelector: string) => {
9
+ window.$(nodeSelector).each((index: number, node: HTMLElement) => {
10
+ const props: AutocompleteProps = { ...window.$(node).data("autocomplete") };
11
+
12
+ ReactDOM.render(
13
+ React.createElement(Autocomplete, props),
14
+ node
15
+ );
16
+ });
17
+ };
@@ -0,0 +1,4 @@
1
+ import { configure } from "enzyme";
2
+ import * as Adapter from "enzyme-adapter-react-16";
3
+
4
+ configure({ adapter: new Adapter() });
@@ -16,10 +16,6 @@ module Decidim
16
16
  def title
17
17
  current_organization.name
18
18
  end
19
-
20
- def foundation_datepicker_locale_tag
21
- javascript_include_tag "datepicker-locales/foundation-datepicker.#{I18n.locale}.js" if I18n.locale != :en
22
- end
23
19
  end
24
20
  end
25
21
  end
@@ -0,0 +1,161 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Admin
5
+ class Permissions < Decidim::DefaultPermissions
6
+ def permissions
7
+ return permission_action if managed_user_action?
8
+
9
+ unless permission_action.scope == :admin
10
+ read_admin_dashboard_action?
11
+ return permission_action
12
+ end
13
+
14
+ unless user
15
+ disallow!
16
+ return permission_action
17
+ end
18
+
19
+ return user_manager_permissions if user_manager?
20
+
21
+ allow! if user_can_enter_space_area?
22
+
23
+ read_admin_dashboard_action?
24
+
25
+ if user.admin?
26
+ allow! if read_admin_log_action?
27
+ allow! if static_page_action?
28
+ allow! if organization_action?
29
+ allow! if user_action?
30
+
31
+ allow! if permission_action.subject == :category
32
+ allow! if permission_action.subject == :component
33
+ allow! if permission_action.subject == :admin_user
34
+ allow! if permission_action.subject == :attachment
35
+ allow! if permission_action.subject == :attachment_collection
36
+ allow! if permission_action.subject == :scope
37
+ allow! if permission_action.subject == :scope_type
38
+ allow! if permission_action.subject == :area
39
+ allow! if permission_action.subject == :area_type
40
+ allow! if permission_action.subject == :newsletter
41
+ allow! if permission_action.subject == :oauth_application
42
+ allow! if permission_action.subject == :user_group
43
+ allow! if permission_action.subject == :officialization
44
+ allow! if permission_action.subject == :authorization
45
+ allow! if permission_action.subject == :authorization_workflow
46
+ end
47
+
48
+ permission_action
49
+ end
50
+
51
+ private
52
+
53
+ def user_manager?
54
+ user && !user.admin? && user.role?("user_manager")
55
+ end
56
+
57
+ def read_admin_dashboard_action?
58
+ return unless permission_action.subject == :admin_dashboard &&
59
+ permission_action.action == :read
60
+
61
+ toggle_allow(user.admin? || space_allows_admin_access_to_current_action?)
62
+ end
63
+
64
+ def read_admin_log_action?
65
+ permission_action.subject == :admin_log &&
66
+ permission_action.action == :read
67
+ end
68
+
69
+ def static_page_action?
70
+ return unless permission_action.subject == :static_page
71
+ static_page = context.fetch(:static_page, nil)
72
+
73
+ case permission_action.action
74
+ when :update
75
+ static_page.present?
76
+ when :update_slug, :destroy
77
+ static_page.present? && !StaticPage.default?(static_page.slug)
78
+ when :update_notable_changes
79
+ static_page.slug == "terms-and-conditions" && static_page.persisted?
80
+ else
81
+ true
82
+ end
83
+ end
84
+
85
+ def organization_action?
86
+ return unless permission_action.subject == :organization
87
+ return unless permission_action.action == :update
88
+
89
+ organization == user.organization
90
+ end
91
+
92
+ def managed_user_action?
93
+ return unless permission_action.subject == :managed_user
94
+ return user_manager_permissions if user_manager?
95
+ return unless user&.admin?
96
+
97
+ case permission_action.action
98
+ when :create
99
+ toggle_allow(!organization.available_authorizations.empty?)
100
+ else
101
+ allow!
102
+ end
103
+
104
+ true
105
+ end
106
+
107
+ def user_action?
108
+ return unless [:user, :impersonatable_user].include?(permission_action.subject)
109
+ subject_user = context.fetch(:user, nil)
110
+
111
+ case permission_action.action
112
+ when :promote
113
+ subject_user.managed? && Decidim::ImpersonationLog.active.where(admin: user).empty?
114
+ when :impersonate
115
+ available_authorization_handlers? &&
116
+ !subject_user.admin? &&
117
+ subject_user.roles.empty? &&
118
+ Decidim::ImpersonationLog.active.where(admin: user).empty?
119
+ when :destroy
120
+ subject_user != user
121
+ else
122
+ true
123
+ end
124
+ end
125
+
126
+ def organization
127
+ @organization ||= context.fetch(:organization, nil) || context.fetch(:current_organization, nil)
128
+ end
129
+
130
+ def user_can_enter_space_area?
131
+ return unless permission_action.action == :enter &&
132
+ permission_action.subject == :space_area
133
+
134
+ space_allows_admin_access_to_current_action?
135
+ end
136
+
137
+ def space_allows_admin_access_to_current_action?
138
+ Decidim.participatory_space_manifests.any? do |manifest|
139
+ begin
140
+ new_permission_action = Decidim::PermissionAction.new(
141
+ action: permission_action.action,
142
+ scope: permission_action.scope,
143
+ subject: permission_action.subject
144
+ )
145
+ manifest.permissions_class.new(user, new_permission_action, context).permissions.allowed?
146
+ rescue Decidim::PermissionAction::PermissionNotSetError
147
+ nil
148
+ end
149
+ end
150
+ end
151
+
152
+ def user_manager_permissions
153
+ Decidim::Admin::UserManagerPermissions.new(user, permission_action, context).permissions
154
+ end
155
+
156
+ def available_authorization_handlers?
157
+ user.organization.available_authorization_handlers.any?
158
+ end
159
+ end
160
+ end
161
+ end