kaui 4.0.27 → 4.0.29
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/app/assets/images/kaui/favicon.svg +29 -0
- data/app/assets/javascripts/kaui/multi_functions_bar_utils.js +23 -3
- data/app/assets/stylesheets/kaui/role_definitions.css +76 -0
- data/app/controllers/kaui/admin_tenants_controller.rb +2 -0
- data/app/controllers/kaui/role_definitions_controller.rb +94 -0
- data/app/models/kaui/role_definition.rb +6 -0
- data/app/views/kaui/accounts/index.html.erb +1 -1
- data/app/views/kaui/admin_tenants/_show_catalog_simple.erb +19 -7
- data/app/views/kaui/charges/_form.html.erb +1 -1
- data/app/views/kaui/credits/_form.html.erb +1 -1
- data/app/views/kaui/home/index.html.erb +1 -0
- data/app/views/kaui/layouts/kaui_header.html.erb +1 -0
- data/app/views/kaui/layouts/kaui_navbar.html.erb +1 -0
- data/app/views/kaui/layouts/kaui_setting_sidebar.html.erb +1 -0
- data/app/views/kaui/role_definitions/_form.html.erb +10 -4
- data/app/views/kaui/role_definitions/edit.html.erb +16 -0
- data/app/views/kaui/role_definitions/index.html.erb +79 -0
- data/app/views/kaui/transactions/_form.html.erb +1 -1
- data/config/routes.rb +4 -1
- data/lib/kaui/version.rb +1 -1
- data/lib/kaui.rb +1 -1
- metadata +6 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: fe249d7727e4018a5ac75692ea7bcd96eabf47c7a088831467e3e92a4fa4bfde
|
|
4
|
+
data.tar.gz: 2531c79e6230ef5b94c3488eebc672053d94a61fac348b44373baeaf7557fedc
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 5b6d597074b06778d4985fed8a1f1343646f00b95837a7dbd041cb63ad0e583d0cb7d856596b01a42ca58be02875929aae6040f4ac57e9fb075dacaed63f305b
|
|
7
|
+
data.tar.gz: e14677cc4af0bd52371fb2ef9bcf62be6db87ffbfcfc1933dc544b1bb06a2841ad9cbcfc7d5728b42dd3e29c879179de8307b9ca581d67f2316833045765249c
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
<svg width="32" height="32" viewBox="-1 -1 38.5 38.5" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<path d="M8.96891 13.6363L17.1663 16.2316L19.867 20.7179L7.22926 20.294L5.87472 17.7276C4.70442 15.5102 6.6717 12.9089 8.96891 13.6363Z" fill="url(#paint0_linear_5656_117635)"/>
|
|
3
|
+
<path d="M2.73109 18.8862L23.0656 19.4261L31.0472 32.6526C31.9039 34.0722 30.9562 35.9453 29.3786 35.9506L14.6421 36C12.8282 36.0061 11.0908 35.2177 9.83259 33.8178L0.749744 23.712C-0.899153 21.8774 0.354861 18.8231 2.73109 18.8862Z" fill="url(#paint1_linear_5656_117635)"/>
|
|
4
|
+
<path d="M20.5179 0.919922L15.7246 7.75567L23.189 11.3725L24.8913 4.89582L20.5179 0.919922Z" fill="url(#paint2_linear_5656_117635)"/>
|
|
5
|
+
<path d="M27.5141 34.8764L15.4574 13.4093C14.4372 11.5929 14.565 9.35199 15.785 7.66255C16.4888 6.68792 17.8875 6.54241 18.778 7.35118L34.1718 21.3321C36.1567 23.1348 36.5779 26.0884 35.1757 28.371L31.1361 34.9469C30.2983 36.3107 28.2978 36.2717 27.5141 34.8764Z" fill="url(#paint3_linear_5656_117635)"/>
|
|
6
|
+
<path d="M32.0753 11.0799L21.0977 3.84213C19.1972 2.5891 20.3796 -0.360792 22.623 0.0364992L27.8828 0.967948C29.1553 1.19329 30.1995 2.09954 30.5986 3.32489L32.9165 10.4422C33.0801 10.9445 32.5171 11.3713 32.0753 11.0799Z" fill="url(#paint4_linear_5656_117635)"/>
|
|
7
|
+
<defs>
|
|
8
|
+
<linearGradient id="paint0_linear_5656_117635" x1="6.3713" y1="14.584" x2="17.3232" y2="20.2038" gradientUnits="userSpaceOnUse">
|
|
9
|
+
<stop stop-color="#004EEB"/>
|
|
10
|
+
<stop offset="1" stop-color="#2970FF"/>
|
|
11
|
+
</linearGradient>
|
|
12
|
+
<linearGradient id="paint1_linear_5656_117635" x1="1.04487" y1="21.155" x2="29.4032" y2="32.4876" gradientUnits="userSpaceOnUse">
|
|
13
|
+
<stop stop-color="#2970FF"/>
|
|
14
|
+
<stop offset="1" stop-color="#7CD4FD"/>
|
|
15
|
+
</linearGradient>
|
|
16
|
+
<linearGradient id="paint2_linear_5656_117635" x1="19.8881" y1="9.67384" x2="23.8884" y2="4.93559" gradientUnits="userSpaceOnUse">
|
|
17
|
+
<stop stop-color="#A6EF67"/>
|
|
18
|
+
<stop offset="1" stop-color="#FDE172"/>
|
|
19
|
+
</linearGradient>
|
|
20
|
+
<linearGradient id="paint3_linear_5656_117635" x1="15.1997" y1="8.83686" x2="29.3077" y2="34.3257" gradientUnits="userSpaceOnUse">
|
|
21
|
+
<stop stop-color="#A6EF67"/>
|
|
22
|
+
<stop offset="1" stop-color="#15B79E"/>
|
|
23
|
+
</linearGradient>
|
|
24
|
+
<linearGradient id="paint4_linear_5656_117635" x1="20.833" y1="1.40851" x2="32.7401" y2="9.43028" gradientUnits="userSpaceOnUse">
|
|
25
|
+
<stop stop-color="#FDE172"/>
|
|
26
|
+
<stop offset="1" stop-color="#EAAA08"/>
|
|
27
|
+
</linearGradient>
|
|
28
|
+
</defs>
|
|
29
|
+
</svg>
|
|
@@ -30,11 +30,23 @@ function searchParseOperatorText(text) {
|
|
|
30
30
|
function getUrlParams() {
|
|
31
31
|
var params = {};
|
|
32
32
|
var advanceSearchQuery = new URLSearchParams(window.location.search).get('advance_search_query');
|
|
33
|
-
|
|
33
|
+
// URLSearchParams already decoded advance_search_query (e.g. 'name[like]=%test%'), so it must not be decoded
|
|
34
|
+
// again: decodeURIComponent throws on the bare '%' of a LIKE value, which aborts the table's draw handler
|
|
35
|
+
// and leaves the DataTables loading indicator on screen.
|
|
36
|
+
var alreadyDecoded = advanceSearchQuery !== null;
|
|
37
|
+
var queryString = alreadyDecoded ? advanceSearchQuery : window.location.search.substring(1).replace(/ac_id/g, 'account_id');
|
|
38
|
+
var decode = function(s) {
|
|
39
|
+
if (alreadyDecoded) return s;
|
|
40
|
+
try {
|
|
41
|
+
return decodeURIComponent(s);
|
|
42
|
+
} catch (e) {
|
|
43
|
+
return s;
|
|
44
|
+
}
|
|
45
|
+
};
|
|
34
46
|
var regex = /([^&=]+)=([^&]*)/g;
|
|
35
47
|
var m;
|
|
36
48
|
while (m = regex.exec(queryString)) {
|
|
37
|
-
params[
|
|
49
|
+
params[decode(m[1])] = decode(m[2]);
|
|
38
50
|
}
|
|
39
51
|
return params;
|
|
40
52
|
}
|
|
@@ -442,7 +454,15 @@ $(document).ready(function() {
|
|
|
442
454
|
var searches = getSavedSearches();
|
|
443
455
|
var params = searches[name];
|
|
444
456
|
if (params) {
|
|
445
|
-
var
|
|
457
|
+
var query;
|
|
458
|
+
if (params.indexOf('_q=1') === 0) {
|
|
459
|
+
// Advanced search: same URL format as the Apply button (see _advanced_search_filterbar.html.erb),
|
|
460
|
+
// which is the one understood by the accounts, invoices and payments pages
|
|
461
|
+
query = 'advance_search_query=' + encodeURIComponent(decodeURIComponent(params));
|
|
462
|
+
} else {
|
|
463
|
+
query = params;
|
|
464
|
+
}
|
|
465
|
+
var newUrl = window.location.protocol + "//" + window.location.host + window.location.pathname + '?' + query;
|
|
446
466
|
window.location.href = newUrl;
|
|
447
467
|
}
|
|
448
468
|
});
|
|
@@ -109,3 +109,79 @@
|
|
|
109
109
|
width: 100% !important;
|
|
110
110
|
outline: none;
|
|
111
111
|
}
|
|
112
|
+
|
|
113
|
+
/* app/views/kaui/role_definitions/index.html.erb (search box styled like the Tags search) */
|
|
114
|
+
|
|
115
|
+
.kaui-users-index #role-definitions-table_filter {
|
|
116
|
+
margin-bottom: 0;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
.kaui-users-index #role-definitions-table_filter label {
|
|
120
|
+
display: flex;
|
|
121
|
+
align-items: center;
|
|
122
|
+
gap: 0.5rem;
|
|
123
|
+
margin-bottom: 0;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
.kaui-users-index #role-definitions-table_filter input {
|
|
127
|
+
width: 20rem;
|
|
128
|
+
height: 2.2rem;
|
|
129
|
+
padding: 0.3rem 1rem;
|
|
130
|
+
margin-left: 0;
|
|
131
|
+
border: 0.0625rem solid var(--kb-outline-primary);
|
|
132
|
+
border-radius: 0.375rem;
|
|
133
|
+
font-weight: 500;
|
|
134
|
+
font-size: 0.875rem;
|
|
135
|
+
line-height: 1.25rem;
|
|
136
|
+
color: var(--kb-on-surface-secondary);
|
|
137
|
+
outline: none;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
.kaui-users-index #role-definitions-table_filter input:focus {
|
|
141
|
+
border-color: var(--kb-primary);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/* Pagination styled like the Tags pagination */
|
|
145
|
+
.kaui-users-index div:has(> div > .dataTables_paginate) {
|
|
146
|
+
margin-top: 1.5rem;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
.kaui-users-index .dataTables_paginate {
|
|
150
|
+
display: flex;
|
|
151
|
+
align-items: center;
|
|
152
|
+
gap: 0.5rem;
|
|
153
|
+
font-family: 'Inter', sans-serif;
|
|
154
|
+
font-size: 0.875rem;
|
|
155
|
+
font-weight: 500;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
.kaui-users-index .dataTables_paginate span .paginate_button {
|
|
159
|
+
width: 2.5rem;
|
|
160
|
+
height: 2.5rem;
|
|
161
|
+
display: inline-flex !important;
|
|
162
|
+
align-items: center !important;
|
|
163
|
+
justify-content: center !important;
|
|
164
|
+
color: var(--kb-on-surface-quaternary) !important;
|
|
165
|
+
text-decoration: none;
|
|
166
|
+
border: 0 !important;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
.kaui-users-index .dataTables_paginate .paginate_button:hover {
|
|
170
|
+
background-color: var(--kb-surface-container);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
.kaui-users-index .dataTables_paginate .paginate_button.current {
|
|
174
|
+
background-color: var(--kb-surface-container) !important;
|
|
175
|
+
border-radius: 0.375rem !important;
|
|
176
|
+
color: var(--kb-on-surface-secondary) !important;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
.kaui-users-index .dataTables_paginate .paginate_button.last,
|
|
180
|
+
.kaui-users-index .dataTables_paginate .paginate_button.previous {
|
|
181
|
+
border: 0.0625rem solid var(--kb-outline-primary);
|
|
182
|
+
border-radius: 0.5rem;
|
|
183
|
+
background-color: var(--kb-neutral-0);
|
|
184
|
+
padding: 0.5rem 0.875rem;
|
|
185
|
+
color: var(--kb-neutral-600);
|
|
186
|
+
}
|
|
187
|
+
|
|
@@ -67,6 +67,8 @@ module Kaui
|
|
|
67
67
|
version_date: effective_date }
|
|
68
68
|
end
|
|
69
69
|
|
|
70
|
+
@is_aviate_catalog = Dependencies::Aviate::Metering.aviate_catalog?(nil, options.merge(jwt_token: cookies[:jwt_token]))
|
|
71
|
+
|
|
70
72
|
@latest_version = begin
|
|
71
73
|
@catalog_versions[-1][:version_date]
|
|
72
74
|
rescue StandardError
|
|
@@ -2,6 +2,56 @@
|
|
|
2
2
|
|
|
3
3
|
module Kaui
|
|
4
4
|
class RoleDefinitionsController < Kaui::EngineController
|
|
5
|
+
DEFAULT_PAGE_SIZE = 20
|
|
6
|
+
|
|
7
|
+
def index
|
|
8
|
+
@search_query = params[:q]
|
|
9
|
+
@offset = params[:offset] || 0
|
|
10
|
+
@limit = params[:limit] || DEFAULT_PAGE_SIZE
|
|
11
|
+
|
|
12
|
+
# The roles are paginated and searched on the server (see #pagination), this only checks that listing is supported
|
|
13
|
+
@max_nb_records = all_role_definitions.size
|
|
14
|
+
rescue StandardError => e
|
|
15
|
+
@max_nb_records = 0
|
|
16
|
+
if e.is_a?(KillBillClient::API::ClientError) && [404, 405].include?(e.response.code.to_i)
|
|
17
|
+
# Listing roles requires Kill Bill 0.25+
|
|
18
|
+
@list_unsupported = true
|
|
19
|
+
else
|
|
20
|
+
flash.now[:error] = "Error while retrieving roles: #{as_string(e)}"
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def pagination
|
|
25
|
+
searcher = lambda do |search_key, offset, limit|
|
|
26
|
+
all = all_role_definitions
|
|
27
|
+
matching = filter_role_definitions(all, search_key)
|
|
28
|
+
page = matching.slice(offset, limit) || []
|
|
29
|
+
max_nb_records = all.size
|
|
30
|
+
total_nb_records = matching.size
|
|
31
|
+
page.define_singleton_method(:pagination_max_nb_records) { max_nb_records }
|
|
32
|
+
page.define_singleton_method(:pagination_total_nb_records) { total_nb_records }
|
|
33
|
+
page
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
data_extractor = lambda do |role_definition, column|
|
|
37
|
+
[
|
|
38
|
+
role_definition.role,
|
|
39
|
+
Array(role_definition.permissions).join(', ')
|
|
40
|
+
][column]
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
formatter = lambda do |role_definition|
|
|
44
|
+
edit_path = view_context.edit_role_definition_path(role_definition.role)
|
|
45
|
+
[
|
|
46
|
+
view_context.link_to(role_definition.role, edit_path),
|
|
47
|
+
Array(role_definition.permissions).join(', '),
|
|
48
|
+
view_context.link_to('Edit', edit_path, class: 'kaui-button edit-button custom-hover text-decoration-none')
|
|
49
|
+
]
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
paginate searcher, data_extractor, formatter
|
|
53
|
+
end
|
|
54
|
+
|
|
5
55
|
def new
|
|
6
56
|
@role_definition = Kaui::RoleDefinition.new
|
|
7
57
|
|
|
@@ -17,6 +67,20 @@ module Kaui
|
|
|
17
67
|
}
|
|
18
68
|
end
|
|
19
69
|
|
|
70
|
+
def edit
|
|
71
|
+
@role_definition = Kaui::RoleDefinition.find_by_name(params.require(:id), options_for_klient)
|
|
72
|
+
|
|
73
|
+
# Kill Bill answers 200 with no permissions for a role that does not exist
|
|
74
|
+
if Array(@role_definition.permissions).empty?
|
|
75
|
+
redirect_to role_definitions_path, flash: { error: "Role '#{params[:id]}' was not found" }
|
|
76
|
+
return
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
@role_definition.permissions = Array(@role_definition.permissions).join(',')
|
|
80
|
+
rescue StandardError => e
|
|
81
|
+
redirect_to role_definitions_path, flash: { error: "Error while retrieving role: #{as_string(e)}" }
|
|
82
|
+
end
|
|
83
|
+
|
|
20
84
|
def create
|
|
21
85
|
# Sanity is done on the server side
|
|
22
86
|
@role_definition = Kaui::RoleDefinition.new(params.require(:role_definition))
|
|
@@ -49,5 +113,35 @@ module Kaui
|
|
|
49
113
|
render action: :new
|
|
50
114
|
end
|
|
51
115
|
end
|
|
116
|
+
|
|
117
|
+
def update
|
|
118
|
+
@role_definition = Kaui::RoleDefinition.new(role: params.require(:id),
|
|
119
|
+
permissions: params.require(:role_definition)[:permissions].to_s.split(',').map(&:strip).compact_blank)
|
|
120
|
+
|
|
121
|
+
begin
|
|
122
|
+
@role_definition.update(current_user.kb_username, params[:reason], params[:comment], options_for_klient)
|
|
123
|
+
redirect_to role_definitions_path, notice: "Role '#{@role_definition.role}' was successfully updated"
|
|
124
|
+
rescue StandardError => e
|
|
125
|
+
@role_definition.permissions = @role_definition.permissions.join(',')
|
|
126
|
+
flash.now[:error] = "Error while updating role: #{as_string(e)}"
|
|
127
|
+
render action: :edit
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
private
|
|
132
|
+
|
|
133
|
+
def all_role_definitions
|
|
134
|
+
Kaui::RoleDefinition.find_all(options_for_klient).sort_by { |role_definition| role_definition.role.to_s }
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
# Case-insensitive match on the role name or any of its permissions
|
|
138
|
+
def filter_role_definitions(role_definitions, search_key)
|
|
139
|
+
return role_definitions if search_key.blank?
|
|
140
|
+
|
|
141
|
+
needle = search_key.to_s.downcase
|
|
142
|
+
role_definitions.select do |role_definition|
|
|
143
|
+
role_definition.role.to_s.downcase.include?(needle) || Array(role_definition.permissions).any? { |permission| permission.to_s.downcase.include?(needle) }
|
|
144
|
+
end
|
|
145
|
+
end
|
|
52
146
|
end
|
|
53
147
|
end
|
|
@@ -2,5 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
module Kaui
|
|
4
4
|
class RoleDefinition < KillBillClient::Model::RoleDefinition
|
|
5
|
+
# Lists all the roles (Kill Bill 0.25+). Defined here because killbill-client releases up to 4.0.9 do not expose it.
|
|
6
|
+
def self.find_all(options = {})
|
|
7
|
+
return super if defined?(super)
|
|
8
|
+
|
|
9
|
+
get "#{KillBillClient::Model::Security::KILLBILL_API_SECURITY_PREFIX}/roles", {}, options
|
|
10
|
+
end
|
|
5
11
|
end
|
|
6
12
|
end
|
|
@@ -108,7 +108,7 @@ $(document).ready(function() {
|
|
|
108
108
|
url: "<%= accounts_pagination_path(:ordering => @ordering, :format => :json) %>",
|
|
109
109
|
headers: {"X-CSRF-Token": $("meta[name='csrf-token']").attr("content")},
|
|
110
110
|
data: function(d) {
|
|
111
|
-
d.advance_search_query = "<%= j(@advance_search_query.to_s) %>";
|
|
111
|
+
d.advance_search_query = "<%= raw j(@advance_search_query.to_s) %>"; // raw: ERB would turn '&' into '&'; j() already makes it safe for a JS string
|
|
112
112
|
return d;
|
|
113
113
|
},
|
|
114
114
|
dataSrc: function(json) {
|
|
@@ -21,13 +21,25 @@
|
|
|
21
21
|
|
|
22
22
|
|
|
23
23
|
<% if can?(:delete, Kaui::AdminTenant) %>
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
24
|
+
<% if @is_aviate_catalog %>
|
|
25
|
+
<span class="d-inline-block" tabindex="0" title="Aviate catalog cannot be deleted">
|
|
26
|
+
<%= render "kaui/components/button/button", {
|
|
27
|
+
label: "Delete Catalog",
|
|
28
|
+
variant: "outline-secondary d-inline-flex align-items-center gap-1",
|
|
29
|
+
type: "button",
|
|
30
|
+
html_class: "kaui-button dots-menu custom-hover",
|
|
31
|
+
html_options: { disabled: true, style: "pointer-events: none;" }
|
|
32
|
+
} %>
|
|
33
|
+
</span>
|
|
34
|
+
<% else %>
|
|
35
|
+
<%= link_to admin_tenant_delete_catalog_path(id: @tenant.id), :method => :delete, class: "text-decoration-none" do %>
|
|
36
|
+
<%= render "kaui/components/button/button", {
|
|
37
|
+
label: "Delete Catalog",
|
|
38
|
+
variant: "outline-secondary d-inline-flex align-items-center gap-1",
|
|
39
|
+
type: "button",
|
|
40
|
+
html_class: "kaui-button dots-menu custom-hover",
|
|
41
|
+
} %>
|
|
42
|
+
<% end %>
|
|
31
43
|
<% end %>
|
|
32
44
|
<% end %>
|
|
33
45
|
<%= link_to download_catalog_xml_path(id: @tenant.id, effective_date: @latest_version), id: "download_link", class: "text-decoration-none" do %>
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
<div class="form-group d-flex pb-3">
|
|
18
18
|
<%= f.label :amount, 'Amount', class: 'col-sm-3 control-label' %>
|
|
19
19
|
<div class="input-group">
|
|
20
|
-
<%= f.number_field :amount, step: :any, id: 'charge_amount', class: 'form-control amount-input', placeholder: '
|
|
20
|
+
<%= f.number_field :amount, step: :any, id: 'charge_amount', class: 'form-control amount-input', placeholder: '0.00' %>
|
|
21
21
|
<div class="input-group-append">
|
|
22
22
|
<% if @invoice.present? %>
|
|
23
23
|
<span class="input-group-text"><%= @invoice.currency %></span>
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
<div class="form-group d-flex pb-3">
|
|
5
5
|
<%= f.label :amount, 'Amount', class: 'col-sm-3 control-label' %>
|
|
6
6
|
<div class="input-group">
|
|
7
|
-
<%= f.number_field :amount, step: :any, id: 'charge_amount', class: 'form-control', placeholder: '
|
|
7
|
+
<%= f.number_field :amount, step: :any, id: 'charge_amount', class: 'form-control', placeholder: '0.00' %>
|
|
8
8
|
|
|
9
9
|
<div>
|
|
10
10
|
<% if @invoice.present? %>
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
<div class="row row-cols-1 row-cols-md-2 g-4 mb-5">
|
|
15
15
|
<%= render partial: "kaui/components/dashboard/setting", locals: { path: kaui_engine.admin_tenants_path, icon: "kaui/dashboard/users.svg", title: "Tenant", desc: "Run multiple tenants for each Kill Bill deployment." } %>
|
|
16
16
|
<%= render partial: "kaui/components/dashboard/setting", locals: { path: kaui_engine.admin_allowed_users_path, icon: "kaui/dashboard/users.svg", title: "Users", desc: "Manage users in Kaui – create user roles, create and edit users, assign roles and tenants to users." } %>
|
|
17
|
+
<%= render partial: "kaui/components/dashboard/setting", locals: { path: kaui_engine.role_definitions_path, icon: "kaui/dashboard/users.svg", title: "Roles", desc: "View and edit role definitions and the permissions they grant." } %>
|
|
17
18
|
<%= render partial: "kaui/components/dashboard/setting", locals: { path: kaui_engine.tags_path, icon: "kaui/dashboard/tags.svg", title: "Tags", desc: "Apply one or more tags to accounts and invoices, a tag being a single value." } %>
|
|
18
19
|
<%= render partial: "kaui/components/dashboard/setting", locals: { path: kaui_engine.custom_fields_path, icon: "kaui/dashboard/custom-field.svg", title: "Custom Fields", desc: "Create custom fields (key/value pairs) and attach them to objects like accounts, payments." } %>
|
|
19
20
|
<% if kpm_plugin_installed %>
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
5
5
|
|
|
6
6
|
<title>Kaui</title>
|
|
7
|
+
<%= favicon_link_tag 'kaui/favicon.svg', rel: 'icon', type: 'image/svg+xml' %>
|
|
7
8
|
<%= stylesheet_link_tag 'application', :media => 'all' %>
|
|
8
9
|
<%= javascript_include_tag 'application' %>
|
|
9
10
|
|
|
@@ -41,6 +41,7 @@
|
|
|
41
41
|
</button>
|
|
42
42
|
<ul class="dropdown-menu">
|
|
43
43
|
<li><%= link_to 'Users', kaui_engine.admin_allowed_users_path, class: 'dropdown-item' %></li>
|
|
44
|
+
<li><%= link_to 'Roles', kaui_engine.role_definitions_path, class: 'dropdown-item' %></li>
|
|
44
45
|
<li><%= link_to 'Tenants', kaui_engine.admin_tenants_path, class: 'dropdown-item' %></li>
|
|
45
46
|
<li><%= link_to 'Admin', kaui_engine.admin_path, class: 'dropdown-item' %></li>
|
|
46
47
|
</ul>
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
session[:tenant_id].present? ? { label: session["kb_tenant_name"], path: kaui_engine.admin_tenant_path(session[:tenant_id]), controller_suffix: "#{session[:tenant_id]}", icon_path: 'kaui/setting/account.svg' } : nil,
|
|
5
5
|
{ label: 'Tenants', path: kaui_engine.admin_tenants_path, controller_suffix: 'admin_tenants', icon_path: 'kaui/setting/tenants.svg' },
|
|
6
6
|
{ label: 'Users', path: kaui_engine.admin_allowed_users_path, controller_suffix: 'admin_allowed_users', icon_path: 'kaui/setting/users.svg' },
|
|
7
|
+
{ label: 'Roles', path: kaui_engine.role_definitions_path, controller_suffix: 'role_definitions', icon_path: 'kaui/setting/users.svg' },
|
|
7
8
|
{ label: 'Tags', path: kaui_engine.tags_path, controller_suffix: 'tags', icon_path: 'kaui/setting/tags.svg' },
|
|
8
9
|
{ label: 'Tag Definitions', path: kaui_engine.tag_definitions_path, controller_suffix: 'tag_definitions', icon_path: 'kaui/setting/tag-definitions.svg' },
|
|
9
10
|
{ label: 'Custom Fields', path: kaui_engine.custom_fields_path, controller_suffix: 'custom_fields', icon_path: 'kaui/setting/custom-field.svg' }
|
|
@@ -1,8 +1,12 @@
|
|
|
1
|
-
|
|
1
|
+
<% editing = local_assigns[:editing] %>
|
|
2
|
+
<%= form_for @role_definition,
|
|
3
|
+
url: (editing ? role_definition_path(@role_definition.role) : role_definitions_path),
|
|
4
|
+
method: (editing ? :put : :post),
|
|
5
|
+
html: { class: 'form-horizontal' } do |f| %>
|
|
2
6
|
<div class="form-group d-flex pb-3">
|
|
3
7
|
<%= f.label :role, 'Role name', class: 'col-sm-3 control-label' %>
|
|
4
8
|
<div class="col-sm-9">
|
|
5
|
-
<%= f.text_field :role, class: 'form-control' %>
|
|
9
|
+
<%= f.text_field :role, class: 'form-control', readonly: editing %>
|
|
6
10
|
</div>
|
|
7
11
|
</div>
|
|
8
12
|
<div class="form-group d-flex pb-3 premissions-group">
|
|
@@ -34,7 +38,7 @@
|
|
|
34
38
|
} %>
|
|
35
39
|
|
|
36
40
|
<%= render "kaui/components/button/button", {
|
|
37
|
-
label: 'Save
|
|
41
|
+
label: (editing ? 'Update Role' : 'Save Role'),
|
|
38
42
|
variant: "outline-secondary d-inline-flex align-items-center gap-1",
|
|
39
43
|
type: "submit",
|
|
40
44
|
html_class: "kaui-dropdown custom-hover",
|
|
@@ -47,7 +51,7 @@
|
|
|
47
51
|
const input = document.getElementById('chip-input');
|
|
48
52
|
const wrapper = document.getElementById('chip-wrapper');
|
|
49
53
|
const hidden = document.getElementById('permissions_hidden');
|
|
50
|
-
let permissions = [];
|
|
54
|
+
let permissions = hidden.value ? hidden.value.split(',').map(p => p.trim()).filter(Boolean) : [];
|
|
51
55
|
|
|
52
56
|
function renderChips() {
|
|
53
57
|
// Remove all chips except the input box
|
|
@@ -91,6 +95,8 @@
|
|
|
91
95
|
input.value = '';
|
|
92
96
|
}
|
|
93
97
|
|
|
98
|
+
renderChips();
|
|
99
|
+
|
|
94
100
|
input.addEventListener('keydown', function (e) {
|
|
95
101
|
if (e.key === 'Enter' || e.key === ',') {
|
|
96
102
|
e.preventDefault();
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
<div class="register kaui-container kaui-role-definitions-new">
|
|
2
|
+
<div class="">
|
|
3
|
+
<div class="" style="max-width: 37.5rem; margin: 0 auto;">
|
|
4
|
+
<h5 class="new-role-definition-title border-bottom">
|
|
5
|
+
<span class="icon-container">
|
|
6
|
+
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
7
|
+
<path d="M13.3334 5.83333C13.3334 7.67428 11.841 9.16667 10.0001 9.16667C8.15913 9.16667 6.66675 7.67428 6.66675 5.83333C6.66675 3.99238 8.15913 2.5 10.0001 2.5C11.841 2.5 13.3334 3.99238 13.3334 5.83333Z" stroke="#414651" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
|
8
|
+
<path d="M15.8334 15.8337C15.8334 13.5325 13.9679 11.667 11.6667 11.667H8.33341C6.03223 11.667 4.16675 13.5325 4.16675 15.8337V17.5003H15.8334V15.8337Z" stroke="#414651" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
|
9
|
+
</svg>
|
|
10
|
+
</span>
|
|
11
|
+
Edit Role Definition
|
|
12
|
+
</h5>
|
|
13
|
+
<%= render 'form', editing: true %>
|
|
14
|
+
</div>
|
|
15
|
+
</div>
|
|
16
|
+
</div>
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
<div class="kaui-container kaui-users-index">
|
|
2
|
+
<%= render partial: 'kaui/components/breadcrumb/breadcrumb', locals: {
|
|
3
|
+
breadcrumbs: [
|
|
4
|
+
{ label: 'Settings', href: '/' },
|
|
5
|
+
{ label: "Roles", href: '#' }
|
|
6
|
+
]
|
|
7
|
+
} %>
|
|
8
|
+
|
|
9
|
+
<div class="d-flex" style="gap: 4rem;">
|
|
10
|
+
<%= render :template => 'kaui/layouts/kaui_setting_sidebar' %>
|
|
11
|
+
|
|
12
|
+
<div class="users-details w-100">
|
|
13
|
+
<div class="d-flex flex-column">
|
|
14
|
+
<div class="users-details-header">
|
|
15
|
+
<h2>Roles</h2>
|
|
16
|
+
<span class="d-flex align-items-start gap-3">
|
|
17
|
+
<span id="role-definitions-search"></span>
|
|
18
|
+
<% if can? :create, Kaui::AdminTenant %>
|
|
19
|
+
<%= link_to new_role_definition_path do %>
|
|
20
|
+
<%= render "kaui/components/button/button", {
|
|
21
|
+
label: "Create Role",
|
|
22
|
+
icon: "kaui/plus.svg",
|
|
23
|
+
variant: "outline-secondary d-inline-flex align-items-center gap-1",
|
|
24
|
+
type: "button",
|
|
25
|
+
html_class: "kaui-dropdown custom-hover",
|
|
26
|
+
} %>
|
|
27
|
+
<% end %>
|
|
28
|
+
<% end %>
|
|
29
|
+
</span>
|
|
30
|
+
</div>
|
|
31
|
+
|
|
32
|
+
<div class="mt-4">
|
|
33
|
+
<% if @list_unsupported %>
|
|
34
|
+
<p>Listing roles requires Kill Bill 0.25 or later.</p>
|
|
35
|
+
<% else %>
|
|
36
|
+
<table id="role-definitions-table" class="allowed-users-table" data-search="<%= @search_query %>">
|
|
37
|
+
<thead>
|
|
38
|
+
<tr>
|
|
39
|
+
<th>Role</th>
|
|
40
|
+
<th>Permissions</th>
|
|
41
|
+
<th></th>
|
|
42
|
+
</tr>
|
|
43
|
+
</thead>
|
|
44
|
+
<tbody>
|
|
45
|
+
</tbody>
|
|
46
|
+
</table>
|
|
47
|
+
<% end %>
|
|
48
|
+
</div>
|
|
49
|
+
</div>
|
|
50
|
+
</div>
|
|
51
|
+
</div>
|
|
52
|
+
</div>
|
|
53
|
+
|
|
54
|
+
<% unless @list_unsupported %>
|
|
55
|
+
<%= javascript_tag do %>
|
|
56
|
+
$(document).ready(function() {
|
|
57
|
+
$('#role-definitions-table').DataTable({
|
|
58
|
+
"dom": "frt<'row'<'col-md-6'i><'col-md-6'p>>",
|
|
59
|
+
"pagingType": "full_numbers",
|
|
60
|
+
"language": {
|
|
61
|
+
"info": "Showing _START_ to _END_ of _TOTAL_ entries",
|
|
62
|
+
"emptyTable": "No roles found.",
|
|
63
|
+
"zeroRecords": "No roles found."
|
|
64
|
+
},
|
|
65
|
+
"pageLength": <%= @limit.to_i %>,
|
|
66
|
+
"displayStart": <%= @offset.to_i %>,
|
|
67
|
+
"ordering": false,
|
|
68
|
+
"processing": true,
|
|
69
|
+
"serverSide": true,
|
|
70
|
+
"search": {"search": $('#role-definitions-table').attr('data-search') || ''},
|
|
71
|
+
"ajax": "<%= role_definitions_pagination_path(:format => :json) %>",
|
|
72
|
+
"initComplete": function() {
|
|
73
|
+
// Show the search box next to the Create Role button, keeping the standard DataTables search styling
|
|
74
|
+
$('#role-definitions-table_filter').appendTo('#role-definitions-search');
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
<% end %>
|
|
79
|
+
<% end %>
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
<div class="form-group d-flex pb-3 border-bottom mb-3">
|
|
16
16
|
<%= f.label :amount, 'Amount', class: 'col-sm-3 control-label' %>
|
|
17
17
|
<div class="input-group">
|
|
18
|
-
<%= f.number_field :amount, step: :any, id: 'charge_amount', class: 'form-control', placeholder: '
|
|
18
|
+
<%= f.number_field :amount, step: :any, id: 'charge_amount', class: 'form-control', placeholder: '0.00', disabled: fix_transaction_state %>
|
|
19
19
|
<div class="input-group-append">
|
|
20
20
|
<% if @invoice.present? %>
|
|
21
21
|
<span class="input-group-text"><%= @invoice.currency %></span>
|
data/config/routes.rb
CHANGED
|
@@ -226,5 +226,8 @@ Kaui::Engine.routes.draw do
|
|
|
226
226
|
post '/add_tenant' => 'admin_allowed_users#add_tenant', :as => 'add_tenant'
|
|
227
227
|
end
|
|
228
228
|
|
|
229
|
-
|
|
229
|
+
scope '/role_definitions' do
|
|
230
|
+
get '/pagination' => 'role_definitions#pagination', :as => 'role_definitions_pagination'
|
|
231
|
+
end
|
|
232
|
+
resources :role_definitions, only: %i[index new create edit update], constraints: { id: %r{[^/]+} }
|
|
230
233
|
end
|
data/lib/kaui/version.rb
CHANGED
data/lib/kaui.rb
CHANGED
|
@@ -172,7 +172,7 @@ module Kaui
|
|
|
172
172
|
values = fields.map do |attr|
|
|
173
173
|
case attr
|
|
174
174
|
when 'auth_amount', 'captured_amount', 'purchased_amount', 'refunded_amount', 'credited_amount'
|
|
175
|
-
view_context.humanized_money_with_symbol(payment&.send(attr.downcase))
|
|
175
|
+
view_context.humanized_money_with_symbol(payment&.send("#{attr.downcase}_to_money"))
|
|
176
176
|
when 'payment_number'
|
|
177
177
|
view_context.link_to(payment.payment_number, view_context.url_for(controller: :payments, action: :show, account_id: payment.account_id, id: payment.payment_id))
|
|
178
178
|
when 'payment_date'
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: kaui
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 4.0.
|
|
4
|
+
version: 4.0.29
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Kill Bill core team
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-10-
|
|
11
|
+
date: 2026-10-29 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: actionpack
|
|
@@ -339,6 +339,7 @@ files:
|
|
|
339
339
|
- app/assets/images/kaui/duck.png
|
|
340
340
|
- app/assets/images/kaui/eye-off.svg
|
|
341
341
|
- app/assets/images/kaui/eye.svg
|
|
342
|
+
- app/assets/images/kaui/favicon.svg
|
|
342
343
|
- app/assets/images/kaui/file-upload.svg
|
|
343
344
|
- app/assets/images/kaui/generate.svg
|
|
344
345
|
- app/assets/images/kaui/header/account.svg
|
|
@@ -663,6 +664,8 @@ files:
|
|
|
663
664
|
- app/views/kaui/registrations/_form.html.erb
|
|
664
665
|
- app/views/kaui/registrations/new.html.erb
|
|
665
666
|
- app/views/kaui/role_definitions/_form.html.erb
|
|
667
|
+
- app/views/kaui/role_definitions/edit.html.erb
|
|
668
|
+
- app/views/kaui/role_definitions/index.html.erb
|
|
666
669
|
- app/views/kaui/role_definitions/new.html.erb
|
|
667
670
|
- app/views/kaui/sessions/_form.html.erb
|
|
668
671
|
- app/views/kaui/sessions/new.html.erb
|
|
@@ -735,7 +738,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
735
738
|
- !ruby/object:Gem::Version
|
|
736
739
|
version: '0'
|
|
737
740
|
requirements: []
|
|
738
|
-
rubygems_version: 3.4.
|
|
741
|
+
rubygems_version: 3.4.19
|
|
739
742
|
signing_key:
|
|
740
743
|
specification_version: 4
|
|
741
744
|
summary: Killbill Admin UI mountable engine
|