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.
- checksums.yaml +4 -4
- data/app/assets/javascripts/decidim/admin/application.js.es6 +5 -1
- data/app/assets/javascripts/decidim/admin/bundle.js +47 -0
- data/app/assets/javascripts/decidim/admin/bundle.js.map +1 -0
- data/app/assets/javascripts/decidim/admin/component_permissions.js.es6 +13 -0
- data/app/assets/javascripts/decidim/admin/managed_users.js.es6 +2 -1
- data/app/assets/javascripts/decidim/admin/subform_toggler.component.js.es6 +14 -7
- data/app/assets/stylesheets/decidim/admin/_decidim.scss +2 -0
- data/app/assets/stylesheets/decidim/admin/bundle.scss +1 -0
- data/app/assets/stylesheets/decidim/admin/components/_autocomplete_select.component.scss +13 -0
- data/app/assets/stylesheets/decidim/admin/modules/_secondary-nav.scss +3 -2
- data/app/assets/stylesheets/decidim/admin/modules/_table-list.scss +7 -0
- data/app/commands/decidim/admin/create_static_page.rb +7 -1
- data/app/commands/decidim/admin/update_component_permissions.rb +9 -3
- data/app/commands/decidim/admin/update_organization_tos_version.rb +47 -0
- data/app/commands/decidim/admin/update_static_page.rb +5 -0
- data/app/constraints/decidim/admin/organization_dashboard_constraint.rb +6 -3
- data/app/controllers/concerns/decidim/admin/participatory_space_admin_context.rb +2 -2
- data/app/controllers/decidim/admin/application_controller.rb +14 -5
- data/app/controllers/decidim/admin/area_types_controller.rb +6 -6
- data/app/controllers/decidim/admin/areas_controller.rb +6 -6
- data/app/controllers/decidim/admin/authorization_workflows_controller.rb +1 -1
- data/app/controllers/decidim/admin/categories_controller.rb +7 -7
- data/app/controllers/decidim/admin/component_permissions_controller.rb +20 -8
- data/app/controllers/decidim/admin/components/base_controller.rb +19 -3
- data/app/controllers/decidim/admin/components_controller.rb +8 -8
- data/app/controllers/decidim/admin/concerns/has_attachment_collections.rb +8 -8
- data/app/controllers/decidim/admin/concerns/has_attachments.rb +11 -9
- data/app/controllers/decidim/admin/concerns/has_private_users.rb +5 -5
- data/app/controllers/decidim/admin/dashboard_controller.rb +4 -2
- data/app/controllers/decidim/admin/exports_controller.rb +1 -1
- data/app/controllers/decidim/admin/impersonatable_users_controller.rb +7 -1
- data/app/controllers/decidim/admin/impersonations_controller.rb +2 -4
- data/app/controllers/decidim/admin/logs_controller.rb +4 -2
- data/app/controllers/decidim/admin/managed_users/impersonation_logs_controller.rb +0 -2
- data/app/controllers/decidim/admin/managed_users/promotions_controller.rb +2 -2
- data/app/controllers/decidim/admin/moderations_controller.rb +4 -4
- data/app/controllers/decidim/admin/newsletters_controller.rb +9 -9
- data/app/controllers/decidim/admin/oauth_applications_controller.rb +7 -7
- data/app/controllers/decidim/admin/officializations_controller.rb +4 -5
- data/app/controllers/decidim/admin/organization_appearance_controller.rb +2 -2
- data/app/controllers/decidim/admin/organization_controller.rb +21 -2
- data/app/controllers/decidim/admin/scope_types_controller.rb +6 -6
- data/app/controllers/decidim/admin/scopes_controller.rb +7 -7
- data/app/controllers/decidim/admin/static_pages_controller.rb +16 -7
- data/app/controllers/decidim/admin/user_groups_controller.rb +3 -3
- data/app/controllers/decidim/admin/users_controller.rb +5 -5
- data/app/forms/decidim/admin/managed_user_promotion_form.rb +1 -1
- data/app/forms/decidim/admin/permission_form.rb +12 -15
- data/app/forms/decidim/admin/static_page_form.rb +1 -0
- data/app/frontend/components/autocomplete.component.test.tsx +19 -0
- data/app/frontend/components/autocomplete.component.tsx +169 -0
- data/app/frontend/entry.ts +17 -0
- data/app/frontend/entry_test.ts +4 -0
- data/app/helpers/decidim/admin/application_helper.rb +0 -4
- data/app/permissions/decidim/admin/permissions.rb +161 -0
- data/app/permissions/decidim/admin/user_manager_permissions.rb +66 -0
- data/app/views/decidim/admin/area_types/index.html.erb +8 -4
- data/app/views/decidim/admin/areas/index.html.erb +6 -3
- data/app/views/decidim/admin/attachment_collections/index.html.erb +3 -3
- data/app/views/decidim/admin/attachment_collections/show.html.erb +2 -2
- data/app/views/decidim/admin/attachments/index.html.erb +3 -3
- data/app/views/decidim/admin/attachments/show.html.erb +2 -2
- data/app/views/decidim/admin/categories/index.html.erb +5 -5
- data/app/views/decidim/admin/categories/show.html.erb +2 -2
- data/app/views/decidim/admin/component_permissions/_options_form.html.erb +14 -0
- data/app/views/decidim/admin/component_permissions/edit.html.erb +37 -16
- data/app/views/decidim/admin/components/_component.html.erb +6 -4
- data/app/views/decidim/admin/components/_form.html.erb +6 -6
- data/app/views/decidim/admin/dashboard/show.html.erb +1 -1
- data/app/views/decidim/admin/impersonatable_users/index.html.erb +5 -3
- data/app/views/decidim/admin/moderations/index.html.erb +2 -2
- data/app/views/decidim/admin/newsletters/index.html.erb +5 -3
- data/app/views/decidim/admin/newsletters/show.html.erb +1 -1
- data/app/views/decidim/admin/oauth_applications/index.html.erb +5 -3
- data/app/views/decidim/admin/participatory_space_private_users/index.html.erb +3 -3
- data/app/views/decidim/admin/scope_types/index.html.erb +5 -3
- data/app/views/decidim/admin/scopes/index.html.erb +4 -4
- data/app/views/decidim/admin/static_pages/_form.html.erb +3 -1
- data/app/views/decidim/admin/static_pages/_form_notable_changes.html.erb +9 -0
- data/app/views/decidim/admin/static_pages/index.html.erb +11 -3
- data/app/views/decidim/admin/static_pages/show.html.erb +2 -2
- data/app/views/decidim/admin/user_groups/index.html.erb +2 -2
- data/app/views/decidim/admin/users/index.html.erb +5 -3
- data/app/views/layouts/decidim/admin/_application.html.erb +0 -1
- data/app/views/layouts/decidim/admin/_template_top.html.erb +1 -0
- data/app/views/layouts/decidim/admin/users.html.erb +4 -4
- data/config/locales/ca.yml +8 -0
- data/config/locales/en.yml +8 -0
- data/config/locales/es.yml +8 -0
- data/config/locales/eu.yml +8 -0
- data/config/locales/fi.yml +8 -0
- data/config/locales/fr.yml +8 -0
- data/config/locales/gl.yml +8 -0
- data/config/locales/it.yml +8 -0
- data/config/locales/nl.yml +8 -0
- data/config/locales/pl.yml +8 -0
- data/config/locales/pt-BR.yml +8 -0
- data/config/locales/pt.yml +8 -0
- data/config/locales/ru.yml +11 -3
- data/config/locales/sv.yml +8 -0
- data/config/locales/uk.yml +8 -0
- data/config/routes.rb +5 -1
- data/lib/decidim/admin.rb +1 -0
- data/lib/decidim/admin/engine.rb +17 -20
- data/lib/decidim/admin/form_builder.rb +64 -0
- data/lib/decidim/admin/test/manage_component_permissions_examples.rb +92 -15
- data/lib/decidim/admin/version.rb +1 -1
- metadata +25 -17
- data/app/models/decidim/admin/abilities/admin_ability.rb +0 -76
- data/app/models/decidim/admin/abilities/base_ability.rb +0 -21
- data/app/models/decidim/admin/abilities/participatory_process_admin_ability.rb +0 -58
- data/app/models/decidim/admin/abilities/participatory_process_collaborator_ability.rb +0 -19
- data/app/models/decidim/admin/abilities/participatory_process_moderator_ability.rb +0 -23
- data/app/models/decidim/admin/abilities/user_manager_ability.rb +0 -34
- 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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
14
|
+
enforce_permission_to :create, :admin_user
|
15
15
|
@form = form(InviteUserForm).instance
|
16
16
|
end
|
17
17
|
|
18
18
|
def create
|
19
|
-
|
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
|
-
|
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
|
-
|
59
|
+
enforce_permission_to :destroy, :admin_user, user: user
|
60
60
|
|
61
61
|
RemoveAdmin.call(user, current_user) do
|
62
62
|
on(:ok) do
|
@@ -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,
|
8
|
+
attribute :options, Hash
|
9
9
|
|
10
|
-
|
11
|
-
|
10
|
+
def manifest
|
11
|
+
Decidim::Verifications.find_workflow_manifest(authorization_handler_name)
|
12
|
+
end
|
12
13
|
|
13
|
-
|
14
|
+
def options_schema
|
15
|
+
@options_schema ||= options_manifest.schema.new(options || {})
|
16
|
+
end
|
14
17
|
|
15
|
-
def
|
16
|
-
|
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
|
-
|
22
|
-
return unless options
|
22
|
+
private
|
23
23
|
|
24
|
-
|
25
|
-
|
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
|
@@ -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,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
|