pg_rails 7.0.8.pre.alpha.52 → 7.0.8.pre.alpha.53
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/pg_engine/app/controllers/admin/users_controller.rb +7 -3
- data/pg_engine/app/controllers/concerns/pg_engine/resource.rb +20 -14
- data/pg_engine/app/controllers/pg_engine/base_controller.rb +3 -3
- data/pg_engine/app/controllers/public/mensaje_contactos_controller.rb +2 -0
- data/pg_engine/app/controllers/users/registrations_controller.rb +1 -3
- data/pg_engine/app/decorators/pg_engine/base_decorator.rb +8 -3
- data/pg_engine/app/helpers/pg_engine/index_helper.rb +2 -0
- data/pg_engine/app/models/pg_engine/base_record.rb +13 -0
- data/pg_engine/app/policies/user_policy.rb +15 -3
- data/pg_engine/app/policies/user_registration_policy.rb +26 -0
- data/pg_engine/app/views/admin/accounts/show.html.slim +1 -1
- data/pg_engine/app/views/admin/user_accounts/show.html.slim +1 -1
- data/pg_engine/app/views/admin/users/show.html.slim +5 -1
- data/pg_engine/config/initializers/active_admin.rb +7 -1
- data/pg_engine/config/initializers/devise.rb +2 -2
- data/pg_engine/config/locales/es.yml +4 -1
- data/pg_engine/config/simple_form/simple_form_bootstrap.rb +1 -1
- data/pg_engine/spec/controllers/admin/accounts_controller_spec.rb +14 -3
- data/pg_engine/spec/controllers/admin/user_accounts_controller_spec.rb +14 -3
- data/pg_engine/spec/controllers/admin/users_controller_spec.rb +14 -3
- data/pg_engine/spec/controllers/concerns/pg_engine/resource_helper_spec.rb +31 -6
- data/pg_engine/spec/controllers/pg_engine/base_controller_spec.rb +2 -2
- data/pg_engine/spec/features/destroy_spec.rb +72 -0
- data/pg_engine/spec/features/login_spec.rb +41 -0
- data/pg_engine/spec/features/signup_spec.rb +78 -0
- data/pg_layout/app/javascript/controllers/navbar_controller.js +9 -0
- data/pg_layout/app/views/devise/sessions/new.html.erb +0 -1
- data/pg_layout/app/views/pg_layout/_navbar.html.erb +9 -3
- data/pg_layout/app/views/pg_layout/_sidebar.html.erb +4 -1
- data/pg_layout/app/views/pg_layout/_sidebar_mobile.html.erb +1 -1
- data/pg_rails/lib/version.rb +1 -1
- data/pg_scaffold/lib/generators/pg_rspec/scaffold/templates/controller_spec.rb +14 -7
- data/pg_scaffold/lib/generators/pg_slim/templates/show.html.slim +1 -1
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bc65c537b0f07c6659a716cf31aca506a9da7d7ee43f6bbaa425a756864875ef
|
4
|
+
data.tar.gz: ba019b72eb7fac96fc364396da6890040a86b7743e2532e73c677a20809c546d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 46fe858cbdfde69a00935a3e92aa2524729a030217629556a3f4a6717b7f873c80ccf72fee9698f0599b0b7768ddd27b392273b01685eb556c46c236a1eb1450
|
7
|
+
data.tar.gz: 3be35c7a9db5507e1c84f62e3b405772986ffb3fd63a09b5a93f5fd54128fca897da7f707437e66556a5aee9f6d26bfe639bdf51dceac99f210730cfd089134d
|
@@ -32,11 +32,15 @@ module Admin
|
|
32
32
|
|
33
33
|
# :nocov:
|
34
34
|
def login_as
|
35
|
-
|
36
|
-
|
35
|
+
return unless dev_user_or_env?
|
36
|
+
|
37
|
+
usuario = User.find(params[:id])
|
38
|
+
if usuario.confirmed_at.present?
|
37
39
|
sign_in(:user, usuario)
|
40
|
+
redirect_to after_sign_in_path_for(usuario)
|
41
|
+
else
|
42
|
+
go_back('No está confirmado')
|
38
43
|
end
|
39
|
-
redirect_to after_sign_in_path_for(usuario)
|
40
44
|
end
|
41
45
|
# :nocov:
|
42
46
|
|
@@ -49,8 +49,7 @@ module PgEngine
|
|
49
49
|
end
|
50
50
|
|
51
51
|
def destroy
|
52
|
-
|
53
|
-
pg_respond_destroy(instancia_modelo, url)
|
52
|
+
pg_respond_destroy(instancia_modelo, params[:redirect_to])
|
54
53
|
end
|
55
54
|
# End public endpoints
|
56
55
|
|
@@ -150,15 +149,21 @@ module PgEngine
|
|
150
149
|
|
151
150
|
def pg_respond_destroy(model, redirect_url = nil)
|
152
151
|
if destroy_model(model)
|
152
|
+
msg = "#{model.model_name.human} #{model.gender == 'f' ? 'borrada' : 'borrado'}"
|
153
153
|
respond_to do |format|
|
154
|
-
|
155
|
-
|
156
|
-
redirect_to redirect_url, notice:
|
157
|
-
|
158
|
-
|
154
|
+
if redirect_url.present?
|
155
|
+
format.html do
|
156
|
+
redirect_to redirect_url, notice: msg, status: :see_other
|
157
|
+
end
|
158
|
+
else
|
159
|
+
format.turbo_stream do
|
160
|
+
render turbo_stream: turbo_stream.remove(model)
|
161
|
+
end
|
162
|
+
format.html do
|
163
|
+
redirect_back(fallback_location: root_path, notice: msg, status: 303)
|
159
164
|
end
|
165
|
+
format.json { head :no_content }
|
160
166
|
end
|
161
|
-
format.json { head :no_content }
|
162
167
|
end
|
163
168
|
else
|
164
169
|
respond_to do |format|
|
@@ -168,11 +173,7 @@ module PgEngine
|
|
168
173
|
render destroy_error_details_view
|
169
174
|
else
|
170
175
|
flash[:alert] = @error_message
|
171
|
-
# if redirect_url.present?
|
172
|
-
# redirect_to redirect_url
|
173
|
-
# else
|
174
176
|
redirect_back(fallback_location: root_path, status: 303)
|
175
|
-
# end
|
176
177
|
end
|
177
178
|
end
|
178
179
|
format.json { render json: { error: @error_message }, status: :unprocessable_entity }
|
@@ -273,7 +274,8 @@ module PgEngine
|
|
273
274
|
|
274
275
|
def do_sort(scope, field, direction)
|
275
276
|
# TODO: restringir ciertos campos?
|
276
|
-
unless scope.model.column_names.include?
|
277
|
+
unless scope.model.column_names.include?(field.to_s) ||
|
278
|
+
scope.model.respond_to?("order_by_#{field}")
|
277
279
|
PgLogger.warn("No existe el campo \"#{field}\"", :warn)
|
278
280
|
return scope
|
279
281
|
end
|
@@ -281,7 +283,11 @@ module PgEngine
|
|
281
283
|
PgLogger.warn("Direction not valid: \"#{direction}\"", :warn)
|
282
284
|
return scope
|
283
285
|
end
|
284
|
-
scope = scope.
|
286
|
+
scope = if scope.model.respond_to? "order_by_#{field}"
|
287
|
+
scope.send "order_by_#{field}", direction
|
288
|
+
else
|
289
|
+
scope.order(field => direction)
|
290
|
+
end
|
285
291
|
instance_variable_set(:@field, field)
|
286
292
|
instance_variable_set(:@direction, direction)
|
287
293
|
scope
|
@@ -99,16 +99,16 @@ module PgEngine
|
|
99
99
|
def not_authorized
|
100
100
|
respond_to do |format|
|
101
101
|
format.json do
|
102
|
-
render json: { error: '
|
102
|
+
render json: { error: 'Acceso no autorizado' },
|
103
103
|
status: :unprocessable_entity
|
104
104
|
end
|
105
105
|
format.html do
|
106
106
|
if request.path == root_path
|
107
107
|
# TODO!: renderear un 500.html y pg_err
|
108
108
|
sign_out(Current.user) if Current.user.present?
|
109
|
-
render plain: '
|
109
|
+
render plain: 'Acceso no autorizado'
|
110
110
|
else
|
111
|
-
go_back('
|
111
|
+
go_back('Acceso no autorizado')
|
112
112
|
end
|
113
113
|
end
|
114
114
|
end
|
@@ -31,12 +31,17 @@ module PgEngine
|
|
31
31
|
end
|
32
32
|
# rubocop:enable Style/MissingRespondToMissing
|
33
33
|
|
34
|
-
def
|
34
|
+
def destroy_link_redirect
|
35
|
+
destroy_link(redirect_to: helpers.url_for(target_index))
|
36
|
+
end
|
37
|
+
|
38
|
+
def destroy_link(confirm_text: '¿Estás seguro?', klass: 'btn-light', redirect_to: nil)
|
35
39
|
return unless Pundit.policy!(Current.user, object).destroy?
|
36
40
|
|
37
41
|
helpers.content_tag :span, rel: :tooltip, title: 'Eliminar' do
|
38
|
-
helpers.link_to object_url
|
39
|
-
|
42
|
+
helpers.link_to object_url + (redirect_to.present? ? "?redirect_to=#{redirect_to}" : ''),
|
43
|
+
data: { 'turbo-confirm': confirm_text, 'turbo-method': :delete },
|
44
|
+
class: "btn btn-sm #{klass}" do
|
40
45
|
helpers.content_tag :span, nil, class: clase_icono('trash-fill')
|
41
46
|
end
|
42
47
|
end
|
@@ -3,6 +3,8 @@
|
|
3
3
|
module PgEngine
|
4
4
|
module IndexHelper
|
5
5
|
def encabezado(campo, options = {})
|
6
|
+
campo = campo.to_s.sub(/_f\z/, '')
|
7
|
+
campo = campo.to_s.sub(/_text\z/, '')
|
6
8
|
clase = options[:clase] || @clase_modelo
|
7
9
|
if options[:ordenable]
|
8
10
|
field = controller.instance_variable_get(:@field)
|
@@ -23,6 +23,10 @@ module PgEngine
|
|
23
23
|
authorizable_ransackable_attributes
|
24
24
|
end
|
25
25
|
|
26
|
+
def gender
|
27
|
+
self.class.model_name.human.downcase.ends_with?('a') ? 'f' : 'm'
|
28
|
+
end
|
29
|
+
|
26
30
|
def self.nombre_plural
|
27
31
|
model_name.human(count: 2)
|
28
32
|
end
|
@@ -43,6 +47,15 @@ module PgEngine
|
|
43
47
|
end
|
44
48
|
end
|
45
49
|
|
50
|
+
# Para el dom_id (index.html)
|
51
|
+
def to_key
|
52
|
+
if respond_to? :hashid
|
53
|
+
[hashid]
|
54
|
+
else
|
55
|
+
super
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
46
59
|
def to_s
|
47
60
|
%i[nombre name].each do |campo|
|
48
61
|
return "#{send(campo)} ##{to_param}" if try(campo).present?
|
@@ -13,7 +13,19 @@ class UserPolicy < ApplicationPolicy
|
|
13
13
|
# end
|
14
14
|
end
|
15
15
|
|
16
|
-
def
|
17
|
-
|
18
|
-
end
|
16
|
+
# def puede_editar?
|
17
|
+
# acceso_total? && !record.readonly?
|
18
|
+
# end
|
19
|
+
|
20
|
+
# def puede_crear?
|
21
|
+
# acceso_total? || user.asesor?
|
22
|
+
# end
|
23
|
+
|
24
|
+
# def puede_borrar?
|
25
|
+
# acceso_total? && !record.readonly?
|
26
|
+
# end
|
27
|
+
|
28
|
+
# def acceso_total?
|
29
|
+
# user.developer?
|
30
|
+
# end
|
19
31
|
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class UserRegistrationPolicy
|
4
|
+
attr_reader :user, :record
|
5
|
+
|
6
|
+
def initialize(user, record)
|
7
|
+
@user = user
|
8
|
+
@record = record
|
9
|
+
end
|
10
|
+
|
11
|
+
def new?
|
12
|
+
create?
|
13
|
+
end
|
14
|
+
|
15
|
+
def create?
|
16
|
+
user.blank?
|
17
|
+
end
|
18
|
+
|
19
|
+
def edit?
|
20
|
+
update?
|
21
|
+
end
|
22
|
+
|
23
|
+
def update?
|
24
|
+
user == record
|
25
|
+
end
|
26
|
+
end
|
@@ -1,9 +1,13 @@
|
|
1
1
|
- content_for :title do
|
2
2
|
= @user.to_s
|
3
3
|
- content_for :actions do
|
4
|
-
= @user.
|
4
|
+
= @user.destroy_link_redirect
|
5
5
|
.ms-1
|
6
6
|
= @user.edit_link
|
7
|
+
.ms-1
|
8
|
+
= link_to admin_login_as_path(id: @user.id), class: 'btn btn-light btn-sm' do
|
9
|
+
span.bi.bi-arrow-right
|
10
|
+
| Login as
|
7
11
|
|
8
12
|
table.table.table-borderless.table-sm.w-auto.mb-0.m-3
|
9
13
|
- atributos_para_mostrar.each do |att|
|
@@ -1,3 +1,9 @@
|
|
1
|
+
class MyAdapter < ActiveAdmin::AuthorizationAdapter
|
2
|
+
def authorized?(action, subject = nil)
|
3
|
+
user.developer?
|
4
|
+
end
|
5
|
+
end
|
6
|
+
|
1
7
|
ActiveAdmin.setup do |config|
|
2
8
|
# == Site Title
|
3
9
|
#
|
@@ -79,7 +85,7 @@ ActiveAdmin.setup do |config|
|
|
79
85
|
# method in a before filter of all controller actions to
|
80
86
|
# ensure that there is a user with proper rights. You can use
|
81
87
|
# CanCanAdapter or make your own. Please refer to documentation.
|
82
|
-
|
88
|
+
config.authorization_adapter = MyAdapter
|
83
89
|
|
84
90
|
# In case you prefer Pundit over other solutions you can here pass
|
85
91
|
# the name of default policy class. This policy will be used in every
|
@@ -164,7 +164,7 @@ Devise.setup do |config|
|
|
164
164
|
|
165
165
|
# ==> Configuration for :rememberable
|
166
166
|
# The time the user will be remembered without asking for credentials again.
|
167
|
-
|
167
|
+
config.remember_for = 60.days
|
168
168
|
|
169
169
|
# Invalidates all the remember me tokens when the user signs out.
|
170
170
|
config.expire_all_remember_me_on_sign_out = true
|
@@ -188,7 +188,7 @@ Devise.setup do |config|
|
|
188
188
|
# ==> Configuration for :timeoutable
|
189
189
|
# The time you want to timeout the user session without activity. After this
|
190
190
|
# time the user will be asked for credentials again. Default is 30 minutes.
|
191
|
-
|
191
|
+
config.timeout_in = 14.days
|
192
192
|
|
193
193
|
# ==> Configuration for :lockable
|
194
194
|
# Defines which strategy will be used to lock an account.
|
@@ -77,7 +77,10 @@ es:
|
|
77
77
|
sign_up: Crear una cuenta
|
78
78
|
forgot_your_password: ¿Olvidaste tu contraseña?
|
79
79
|
didn_t_receive_confirmation_instructions: ¿No recibiste las instrucciones para confirmar tu cuenta?
|
80
|
-
|
80
|
+
activerecord:
|
81
|
+
attributes:
|
82
|
+
user:
|
83
|
+
remember_me: Mantener sesión abierta
|
81
84
|
|
82
85
|
|
83
86
|
|
@@ -92,7 +92,7 @@ SimpleForm.setup do |config|
|
|
92
92
|
config.wrappers :vertical_form, class: 'mb-3', &control_wrapper
|
93
93
|
|
94
94
|
# vertical input for boolean
|
95
|
-
config.wrappers :vertical_boolean, tag: 'fieldset', class: 'mb-3' do |b|
|
95
|
+
config.wrappers :vertical_boolean, tag: 'fieldset', class: 'mb-3 d-flex justify-content-center' do |b|
|
96
96
|
b.use :html5
|
97
97
|
b.optional :readonly
|
98
98
|
b.wrapper :form_check_wrapper, class: 'form-check' do |bb|
|
@@ -184,10 +184,12 @@ RSpec.describe Admin::AccountsController do
|
|
184
184
|
|
185
185
|
describe 'DELETE #destroy' do
|
186
186
|
subject do
|
187
|
-
|
187
|
+
request.headers['Accept'] = 'text/vnd.turbo-stream.html,text/html'
|
188
|
+
delete :destroy, params: { id: account.to_param, redirect_to: redirect_url }
|
188
189
|
end
|
189
190
|
|
190
191
|
let!(:account) { create :account }
|
192
|
+
let(:redirect_url) { nil }
|
191
193
|
|
192
194
|
it 'destroys the requested account' do
|
193
195
|
expect { subject }.to change(Account.kept, :count).by(-1)
|
@@ -198,9 +200,18 @@ RSpec.describe Admin::AccountsController do
|
|
198
200
|
expect(account.reload.discarded_at).to be_present
|
199
201
|
end
|
200
202
|
|
201
|
-
it '
|
203
|
+
it 'quita el elemento de la lista' do
|
202
204
|
subject
|
203
|
-
expect(response).to
|
205
|
+
expect(response.body).to include('turbo-stream action="remove"')
|
206
|
+
end
|
207
|
+
|
208
|
+
context 'si hay redirect_to' do
|
209
|
+
let(:redirect_url) { admin_accounts_url }
|
210
|
+
|
211
|
+
it 'redirects to the accounts list' do
|
212
|
+
subject
|
213
|
+
expect(response).to redirect_to(admin_accounts_url)
|
214
|
+
end
|
204
215
|
end
|
205
216
|
end
|
206
217
|
end
|
@@ -172,18 +172,29 @@ RSpec.describe Admin::UserAccountsController do
|
|
172
172
|
|
173
173
|
describe 'DELETE #destroy' do
|
174
174
|
subject do
|
175
|
-
|
175
|
+
request.headers['Accept'] = 'text/vnd.turbo-stream.html,text/html'
|
176
|
+
delete :destroy, params: { id: user_account.to_param, redirect_to: redirect_url }
|
176
177
|
end
|
177
178
|
|
178
179
|
let!(:user_account) { create :user_account }
|
180
|
+
let(:redirect_url) { nil }
|
179
181
|
|
180
182
|
it 'destroys the requested user_account' do
|
181
183
|
expect { subject }.to change(UserAccount, :count).by(-1)
|
182
184
|
end
|
183
185
|
|
184
|
-
it '
|
186
|
+
it 'quita el elemento de la lista' do
|
185
187
|
subject
|
186
|
-
expect(response).to
|
188
|
+
expect(response.body).to include('turbo-stream action="remove"')
|
189
|
+
end
|
190
|
+
|
191
|
+
context 'si hay redirect_to' do
|
192
|
+
let(:redirect_url) { admin_user_accounts_url }
|
193
|
+
|
194
|
+
it 'redirects to the user_accounts list' do
|
195
|
+
subject
|
196
|
+
expect(response).to redirect_to(admin_user_accounts_url)
|
197
|
+
end
|
187
198
|
end
|
188
199
|
end
|
189
200
|
end
|
@@ -158,10 +158,12 @@ RSpec.describe Admin::UsersController do
|
|
158
158
|
|
159
159
|
describe 'DELETE #destroy' do
|
160
160
|
subject do
|
161
|
-
|
161
|
+
request.headers['Accept'] = 'text/vnd.turbo-stream.html,text/html'
|
162
|
+
delete :destroy, params: { id: user.to_param, redirect_to: redirect_url }
|
162
163
|
end
|
163
164
|
|
164
165
|
let!(:user) { create :user }
|
166
|
+
let(:redirect_url) { nil }
|
165
167
|
|
166
168
|
it 'destroys the requested user' do
|
167
169
|
expect { subject }.to change(User.kept, :count).by(-1)
|
@@ -172,9 +174,18 @@ RSpec.describe Admin::UsersController do
|
|
172
174
|
expect(user.reload.discarded_at).to be_present
|
173
175
|
end
|
174
176
|
|
175
|
-
it '
|
177
|
+
it 'quita el elemento de la lista' do
|
176
178
|
subject
|
177
|
-
expect(response).to
|
179
|
+
expect(response.body).to include('turbo-stream action="remove"')
|
180
|
+
end
|
181
|
+
|
182
|
+
context 'si hay redirect_to' do
|
183
|
+
let(:redirect_url) { admin_users_url }
|
184
|
+
|
185
|
+
it 'redirects to the users list' do
|
186
|
+
subject
|
187
|
+
expect(response).to redirect_to(admin_users_url)
|
188
|
+
end
|
178
189
|
end
|
179
190
|
end
|
180
191
|
end
|
@@ -34,9 +34,9 @@ describe PgEngine::Resource do
|
|
34
34
|
instancia.send(:do_sort, scope, param, direction)
|
35
35
|
end
|
36
36
|
|
37
|
-
let!(:
|
38
|
-
let!(:
|
39
|
-
let(:scope) {
|
37
|
+
let!(:cosa_ult) { create :cosa, nombre: 'Z' }
|
38
|
+
let!(:cosa_pri) { create :cosa, nombre: 'a' }
|
39
|
+
let(:scope) { Cosa.all }
|
40
40
|
let(:param) { :nombre }
|
41
41
|
let(:direction) { :desc }
|
42
42
|
|
@@ -44,7 +44,7 @@ describe PgEngine::Resource do
|
|
44
44
|
let(:direction) { :asc }
|
45
45
|
|
46
46
|
it do
|
47
|
-
expect(subject.to_a).to eq [
|
47
|
+
expect(subject.to_a).to eq [cosa_pri, cosa_ult]
|
48
48
|
end
|
49
49
|
end
|
50
50
|
|
@@ -52,7 +52,7 @@ describe PgEngine::Resource do
|
|
52
52
|
let(:direction) { :desc }
|
53
53
|
|
54
54
|
it do
|
55
|
-
expect(subject.to_a).to eq [
|
55
|
+
expect(subject.to_a).to eq [cosa_ult, cosa_pri]
|
56
56
|
end
|
57
57
|
end
|
58
58
|
|
@@ -60,7 +60,32 @@ describe PgEngine::Resource do
|
|
60
60
|
let(:param) { :inexistente }
|
61
61
|
|
62
62
|
it do
|
63
|
-
expect(subject.to_a).to eq [
|
63
|
+
expect(subject.to_a).to eq [cosa_ult, cosa_pri]
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
context 'cuando ordeno por categoria' do
|
68
|
+
let(:param) { :categoria_de_cosa }
|
69
|
+
|
70
|
+
before do
|
71
|
+
cosa_pri.categoria_de_cosa.update_column(:nombre, 'a') # rubocop:disable Rails/SkipsModelValidations
|
72
|
+
cosa_ult.categoria_de_cosa.update_column(:nombre, 'z') # rubocop:disable Rails/SkipsModelValidations
|
73
|
+
end
|
74
|
+
|
75
|
+
context 'si es asc' do
|
76
|
+
let(:direction) { :asc }
|
77
|
+
|
78
|
+
it do
|
79
|
+
expect(subject.to_a).to eq [cosa_pri, cosa_ult]
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
context 'si es desc' do
|
84
|
+
let(:direction) { :desc }
|
85
|
+
|
86
|
+
it do
|
87
|
+
expect(subject.to_a).to eq [cosa_ult, cosa_pri]
|
88
|
+
end
|
64
89
|
end
|
65
90
|
end
|
66
91
|
end
|
@@ -42,7 +42,7 @@ describe DummyBaseController do
|
|
42
42
|
it do
|
43
43
|
subject
|
44
44
|
expect(response).to redirect_to root_path
|
45
|
-
expect(flash[:alert]).to eq '
|
45
|
+
expect(flash[:alert]).to eq 'Acceso no autorizado'
|
46
46
|
expect(controller).to be_user_signed_in
|
47
47
|
end
|
48
48
|
|
@@ -54,7 +54,7 @@ describe DummyBaseController do
|
|
54
54
|
it do
|
55
55
|
subject
|
56
56
|
expect(response).to have_http_status(:ok)
|
57
|
-
expect(response.body).to eq '
|
57
|
+
expect(response.body).to eq 'Acceso no autorizado'
|
58
58
|
expect(controller).not_to be_user_signed_in
|
59
59
|
end
|
60
60
|
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rails_helper'
|
4
|
+
|
5
|
+
describe 'Sign in', :js do
|
6
|
+
include ActionView::RecordIdentifier
|
7
|
+
|
8
|
+
shared_examples 'destroy from index' do
|
9
|
+
subject do
|
10
|
+
accept_confirm do
|
11
|
+
find("##{dom_id(cosa)} span[title=Eliminar] a").click
|
12
|
+
end
|
13
|
+
sleep 1
|
14
|
+
end
|
15
|
+
|
16
|
+
let(:user) { create :user, :developer }
|
17
|
+
let!(:cosa) { create :cosa }
|
18
|
+
|
19
|
+
before do
|
20
|
+
create_list :cosa, 5
|
21
|
+
login_as user
|
22
|
+
visit '/frontend/cosas'
|
23
|
+
end
|
24
|
+
|
25
|
+
it do
|
26
|
+
expect { subject }.to change { page.find_all('tbody tr').length }.from(6).to(5)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
shared_examples 'destroy from show' do
|
31
|
+
subject do
|
32
|
+
accept_confirm do
|
33
|
+
find('.btn-toolbar span[title=Eliminar] a').click
|
34
|
+
end
|
35
|
+
sleep 1
|
36
|
+
end
|
37
|
+
|
38
|
+
let(:user) { create :user, :developer }
|
39
|
+
let!(:cosa) { create :cosa }
|
40
|
+
|
41
|
+
before do
|
42
|
+
login_as user
|
43
|
+
visit "/frontend/cosas/#{cosa.to_param}"
|
44
|
+
end
|
45
|
+
|
46
|
+
it do # rubocop:disable RSpec/MultipleExpectations
|
47
|
+
subject
|
48
|
+
expect(page).to have_current_path('/frontend/cosas')
|
49
|
+
expect(page).to have_text('Coso borrado')
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# Capybara.drivers.keys
|
54
|
+
drivers = %i[
|
55
|
+
selenium_headless
|
56
|
+
selenium_chrome_headless
|
57
|
+
selenium_chrome_headless_notebook
|
58
|
+
selenium_chrome_headless_iphone
|
59
|
+
]
|
60
|
+
# drivers = %i[selenium_chrome_headless_notebook]
|
61
|
+
# drivers = %i[selenium_chrome_debugger]
|
62
|
+
# drivers = %i[selenium]
|
63
|
+
# drivers = %i[selenium_chrome]
|
64
|
+
drivers = [ENV['DRIVER'].to_sym] if ENV['DRIVER'].present?
|
65
|
+
|
66
|
+
drivers.each do |driver|
|
67
|
+
context("with driver '#{driver}'", driver:) do
|
68
|
+
it_behaves_like 'destroy from index'
|
69
|
+
it_behaves_like 'destroy from show'
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rails_helper'
|
4
|
+
|
5
|
+
describe 'Sign in', :js do
|
6
|
+
shared_examples 'sign_in' do
|
7
|
+
subject do
|
8
|
+
visit '/users/sign_in'
|
9
|
+
fill_in 'user_email', with: user.email
|
10
|
+
fill_in 'user_password', with: password
|
11
|
+
find('input[type=submit]').click
|
12
|
+
end
|
13
|
+
|
14
|
+
let(:password) { 'pass1234' }
|
15
|
+
let!(:user) { create :user, password: }
|
16
|
+
|
17
|
+
it do
|
18
|
+
subject
|
19
|
+
expect(page).to have_text :all, 'No hay categorías de cosas aún'
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# Capybara.drivers.keys
|
24
|
+
drivers = %i[
|
25
|
+
selenium_headless
|
26
|
+
selenium_chrome_headless
|
27
|
+
selenium_chrome_headless_notebook
|
28
|
+
selenium_chrome_headless_iphone
|
29
|
+
]
|
30
|
+
# drivers = %i[selenium_chrome_headless_notebook]
|
31
|
+
# drivers = %i[selenium_chrome_debugger]
|
32
|
+
# drivers = %i[selenium]
|
33
|
+
# drivers = %i[selenium_chrome]
|
34
|
+
drivers = [ENV['DRIVER'].to_sym] if ENV['DRIVER'].present?
|
35
|
+
|
36
|
+
drivers.each do |driver|
|
37
|
+
context("with driver '#{driver}'", driver:) do
|
38
|
+
include_examples 'sign_in'
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rails_helper'
|
4
|
+
|
5
|
+
describe 'Al Registrarse', :js do
|
6
|
+
include ActiveJob::TestHelper
|
7
|
+
|
8
|
+
find_scroll = proc do |selector, options = {}|
|
9
|
+
elem = find(selector, **options.merge(visible: :all))
|
10
|
+
script = 'arguments[0].scrollIntoView({ behavior: "instant", block: "start", inline: "nearest" });'
|
11
|
+
page.execute_script(script, elem)
|
12
|
+
sleep 0.5
|
13
|
+
elem
|
14
|
+
end
|
15
|
+
|
16
|
+
shared_examples 'sign_up' do
|
17
|
+
subject do
|
18
|
+
perform_enqueued_jobs do
|
19
|
+
visit '/users/sign_up'
|
20
|
+
fill_in 'user_email', with: Faker::Internet.email
|
21
|
+
fill_in 'user_nombre', with: Faker::Name.name
|
22
|
+
fill_in 'user_apellido', with: Faker::Name.name
|
23
|
+
fill_in 'user_password', with: 'admin123'
|
24
|
+
fill_in 'user_password_confirmation', with: 'admin123'
|
25
|
+
instance_exec('input[type=submit]', &find_scroll).click
|
26
|
+
expect(page).to have_text('Se ha enviado un mensaje con un enlace')
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'guarda el user' do
|
31
|
+
expect { subject }.to change(User, :count).by(1)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
shared_examples 'edit user' do
|
36
|
+
subject do
|
37
|
+
fill_in 'user_nombre', with: 'despues'
|
38
|
+
fill_in 'user_current_password', with: password
|
39
|
+
instance_exec('input[type=submit]', &find_scroll).click
|
40
|
+
# find('').click
|
41
|
+
sleep 1
|
42
|
+
end
|
43
|
+
|
44
|
+
let(:password) { 'pass1234' }
|
45
|
+
let(:nombre) { 'antes' }
|
46
|
+
let!(:user) { create :user, password:, nombre: }
|
47
|
+
|
48
|
+
before do
|
49
|
+
login_as user
|
50
|
+
visit '/users/edit'
|
51
|
+
end
|
52
|
+
|
53
|
+
it do # rubocop:disable RSpec/MultipleExpectations
|
54
|
+
expect { subject }.to change { user.reload.nombre }.to('despues')
|
55
|
+
expect(page).to have_text('Tu cuenta se ha actualizado')
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
# Capybara.drivers.keys
|
60
|
+
drivers = %i[
|
61
|
+
selenium_headless
|
62
|
+
selenium_chrome_headless
|
63
|
+
selenium_chrome_headless_notebook
|
64
|
+
selenium_chrome_headless_iphone
|
65
|
+
]
|
66
|
+
# drivers = %i[selenium_chrome_headless_notebook]
|
67
|
+
# drivers = %i[selenium_chrome_debugger]
|
68
|
+
# drivers = %i[selenium]
|
69
|
+
# drivers = %i[selenium_chrome]
|
70
|
+
drivers = [ENV['DRIVER'].to_sym] if ENV['DRIVER'].present?
|
71
|
+
|
72
|
+
drivers.each do |driver|
|
73
|
+
context("with driver '#{driver}'", driver:) do
|
74
|
+
it_behaves_like 'sign_up'
|
75
|
+
it_behaves_like 'edit user'
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -1,15 +1,24 @@
|
|
1
1
|
import { Controller } from '@hotwired/stimulus'
|
2
2
|
import Cookies from './../utils/cookies'
|
3
|
+
import { fadeOut, fadeIn } from './../utils/utils'
|
3
4
|
|
4
5
|
export default class extends Controller {
|
6
|
+
connect () {
|
7
|
+
if (document.getElementById('sidebar').classList.contains('opened')) {
|
8
|
+
document.querySelector('.navbar .navbar-brand').style.visibility = 'hidden'
|
9
|
+
}
|
10
|
+
}
|
11
|
+
|
5
12
|
expandNavbar (e) {
|
6
13
|
const icon = this.element.querySelector('i')
|
7
14
|
if (document.getElementById('sidebar').classList.toggle('opened')) {
|
8
15
|
icon.classList.add('bi-chevron-left')
|
9
16
|
icon.classList.remove('bi-chevron-right')
|
17
|
+
fadeOut(document.querySelector('.navbar .navbar-brand'))
|
10
18
|
} else {
|
11
19
|
icon.classList.remove('bi-chevron-left')
|
12
20
|
icon.classList.add('bi-chevron-right')
|
21
|
+
fadeIn(document.querySelector('.navbar .navbar-brand'))
|
13
22
|
}
|
14
23
|
const isOpened = document.getElementById('sidebar').classList.contains('opened')
|
15
24
|
new Cookies().setCookie('navbar_expand', isOpened, 30)
|
@@ -5,13 +5,19 @@
|
|
5
5
|
<i class="bi <%= @navbar_chevron_class %>"></i>
|
6
6
|
</button>
|
7
7
|
|
8
|
-
<button class="btn btn-outline-light d-inline-block d-<%= @breakpoint_navbar_expand %>-none" type="button" data-bs-toggle="offcanvas" data-bs-target="#offcanvasExample" aria-controls="offcanvasExample">
|
9
|
-
<i class="bi bi-list"></i>
|
10
|
-
</button>
|
11
8
|
<% end %>
|
12
9
|
<% @navbar.extensiones.each do |extension| %>
|
13
10
|
<%= extension %>
|
14
11
|
<% end %>
|
15
12
|
<%= @navbar.logo if @navbar.logo.present? %>
|
13
|
+
<button class="btn btn-outline-light d-inline-block d-<%= @breakpoint_navbar_expand %>-none" type="button" data-bs-toggle="offcanvas" data-bs-target="#offcanvasExample" aria-controls="offcanvasExample">
|
14
|
+
<i class="bi bi-list"></i>
|
15
|
+
</button>
|
16
16
|
</div>
|
17
17
|
</nav>
|
18
|
+
|
19
|
+
<style type="text/css" media="(max-width: 767px)">
|
20
|
+
.navbar .navbar-brand {
|
21
|
+
visibility:visible!important;
|
22
|
+
}
|
23
|
+
</style>
|
@@ -1,5 +1,8 @@
|
|
1
1
|
<div id="sidebar" class="<%= @navbar_opened_class %> flex-shrink-0 d-none d-<%= @breakpoint_navbar_expand %>-block">
|
2
|
-
<div class="mt-
|
2
|
+
<div class="mt-1">
|
3
|
+
<div class="m-3">
|
4
|
+
<%= @navbar.logo if @navbar.logo.present? %>
|
5
|
+
</div>
|
3
6
|
<% if user_signed_in? %>
|
4
7
|
<span class="ms-3 text-light"><%= Current.user %></span>
|
5
8
|
<hr>
|
@@ -1,4 +1,4 @@
|
|
1
|
-
<div class="offcanvas offcanvas-
|
1
|
+
<div class="offcanvas offcanvas-end" tabindex="-1" id="offcanvasExample" aria-labelledby="offcanvasExampleLabel">
|
2
2
|
<div class="offcanvas-header" data-bs-theme="dark">
|
3
3
|
<h5 class="offcanvas-title" id="offcanvasExampleLabel"></h5>
|
4
4
|
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" aria-label="Close"></button>
|
data/pg_rails/lib/version.rb
CHANGED
@@ -241,14 +241,12 @@ RSpec.describe <%= controller_class_name %>Controller do
|
|
241
241
|
|
242
242
|
describe 'DELETE #destroy' do
|
243
243
|
subject do
|
244
|
-
|
245
|
-
delete :destroy, { id: <%= file_name %>.to_param }
|
246
|
-
<% else -%>
|
247
|
-
delete :destroy, params: { id: <%= file_name %>.to_param }
|
248
|
-
<% end -%>
|
244
|
+
request.headers['Accept'] = "text/vnd.turbo-stream.html,text/html"
|
245
|
+
delete :destroy, params: { id: <%= file_name %>.to_param, redirect_to: redirect_url }
|
249
246
|
end
|
250
247
|
|
251
248
|
let!(:<%= nombre_tabla_completo_singular %>) { create :<%= nombre_tabla_completo_singular %> }
|
249
|
+
let(:redirect_url) { nil }
|
252
250
|
|
253
251
|
it 'destroys the requested <%= nombre_tabla_completo_singular %>' do
|
254
252
|
<% if options[:discard] -%>
|
@@ -267,9 +265,18 @@ RSpec.describe <%= controller_class_name %>Controller do
|
|
267
265
|
end
|
268
266
|
|
269
267
|
<% end -%>
|
270
|
-
it '
|
268
|
+
it 'quita el elemento de la lista' do
|
271
269
|
subject
|
272
|
-
expect(response).to
|
270
|
+
expect(response.body).to include('turbo-stream action="remove"')
|
271
|
+
end
|
272
|
+
|
273
|
+
context 'si hay redirect_to' do
|
274
|
+
let(:redirect_url) { <%= index_helper %>_url }
|
275
|
+
|
276
|
+
it 'redirects to the <%= table_name %> list' do
|
277
|
+
subject
|
278
|
+
expect(response).to redirect_to(<%= index_helper %>_url)
|
279
|
+
end
|
273
280
|
end
|
274
281
|
end
|
275
282
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pg_rails
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 7.0.8.pre.alpha.
|
4
|
+
version: 7.0.8.pre.alpha.53
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Martín Rosso
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-05-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -890,6 +890,7 @@ files:
|
|
890
890
|
- pg_engine/app/policies/pg_engine/application_policy.rb
|
891
891
|
- pg_engine/app/policies/user_account_policy.rb
|
892
892
|
- pg_engine/app/policies/user_policy.rb
|
893
|
+
- pg_engine/app/policies/user_registration_policy.rb
|
893
894
|
- pg_engine/app/views/admin/accounts/_account.html.slim
|
894
895
|
- pg_engine/app/views/admin/accounts/_form.html.slim
|
895
896
|
- pg_engine/app/views/admin/accounts/edit.html.slim
|
@@ -956,6 +957,9 @@ files:
|
|
956
957
|
- pg_engine/spec/factories/mensaje_contactos.rb
|
957
958
|
- pg_engine/spec/factories/user_accounts.rb
|
958
959
|
- pg_engine/spec/factories/users.rb
|
960
|
+
- pg_engine/spec/features/destroy_spec.rb
|
961
|
+
- pg_engine/spec/features/login_spec.rb
|
962
|
+
- pg_engine/spec/features/signup_spec.rb
|
959
963
|
- pg_engine/spec/fixtures/test.pdf
|
960
964
|
- pg_engine/spec/helpers/pg_engine/pg_rails_helper_spec.rb
|
961
965
|
- pg_engine/spec/lib/pg_engine/error_helper_spec.rb
|