kaui 4.0.28 → 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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1e729c6fc5b318da0970ac53952495ace863cb116267af5774c235aa2012e14c
4
- data.tar.gz: 1a7fb48b4e653dd6d4a136f37e297cd66ce2ee1fc33ab89cf2adec6e1eacd35a
3
+ metadata.gz: fe249d7727e4018a5ac75692ea7bcd96eabf47c7a088831467e3e92a4fa4bfde
4
+ data.tar.gz: 2531c79e6230ef5b94c3488eebc672053d94a61fac348b44373baeaf7557fedc
5
5
  SHA512:
6
- metadata.gz: 9a3eed6c7fe79ef695471e02db83ab562e7da2e355f712d9876f971a28db4b86fa9de278c5925aded58a183009555c87f30dadbc0568ac6386b4c5d929c9d0bc
7
- data.tar.gz: 45bd2f51b5de3217c0bc50edf837456b797d99cd568e96cd5c674cbd4812c82418d51c90c6449ee7e830af8c28e86c61529df9554c958b7e4f9b9d9d6f798189
6
+ metadata.gz: 5b6d597074b06778d4985fed8a1f1343646f00b95837a7dbd041cb63ad0e583d0cb7d856596b01a42ca58be02875929aae6040f4ac57e9fb075dacaed63f305b
7
+ data.tar.gz: e14677cc4af0bd52371fb2ef9bcf62be6db87ffbfcfc1933dc544b1bb06a2841ad9cbcfc7d5728b42dd3e29c879179de8307b9ca581d67f2316833045765249c
@@ -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
@@ -21,13 +21,25 @@
21
21
 
22
22
 
23
23
  <% if can?(:delete, Kaui::AdminTenant) %>
24
- <%= link_to admin_tenant_delete_catalog_path(id: @tenant.id), :method => :delete, class: "text-decoration-none" do %>
25
- <%= render "kaui/components/button/button", {
26
- label: "Delete Catalog",
27
- variant: "outline-secondary d-inline-flex align-items-center gap-1",
28
- type: "button",
29
- html_class: "kaui-button dots-menu custom-hover",
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: '$ 0.00' %>
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: '$ 0.00' %>
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 %>
@@ -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
- <%= form_for @role_definition, html: { class: 'form-horizontal' } do |f| %>
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 User',
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: '$ 0.00', disabled: fix_transaction_state %>
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
- resources :role_definitions, only: %i[new create]
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Kaui
4
- VERSION = '4.0.28'
4
+ VERSION = '4.0.29'
5
5
  end
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.28
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-21 00:00:00.000000000 Z
11
+ date: 2026-10-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: actionpack
@@ -664,6 +664,8 @@ files:
664
664
  - app/views/kaui/registrations/_form.html.erb
665
665
  - app/views/kaui/registrations/new.html.erb
666
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
667
669
  - app/views/kaui/role_definitions/new.html.erb
668
670
  - app/views/kaui/sessions/_form.html.erb
669
671
  - app/views/kaui/sessions/new.html.erb