diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb
new file mode 100644
index 0000000..fdea8a5
--- /dev/null
+++ b/app/controllers/users_controller.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+class UsersController < ApplicationController
+ def index
+ @users = User.all.order(created_at: :desc)
+ @user = User.new
+ end
+
+ def create
+ user = User.create(password: SecureRandom.hex, created_by: current_user, **user_params)
+
+ user.send_reset_password_instructions if user.persisted?
+
+ redirect_to users_path
+ end
+
+ def destroy
+ user = User.find(params[:id])
+ user.destroy
+
+ sign_out(current_user) if user == current_user
+
+ redirect_to users_path
+ end
+
+ private
+
+ def user_params
+ @user_params ||= params.require(:user).permit(:email)
+ end
+end
diff --git a/app/models/user.rb b/app/models/user.rb
index b9b9c0a..5124eba 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -1,6 +1,12 @@
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
- devise :database_authenticatable,
+ devise :database_authenticatable,
:recoverable, :rememberable, :validatable, :lockable, :timeoutable
+
+ # Trazabilidad
+ #
+ # @see {https://guides.rubyonrails.org/association_basics.html#self-joins}
+ belongs_to :created_by, class_name: 'User', optional: true
+ has_many :created, class_name: 'User', foreign_key: 'created_by_id'
end
diff --git a/app/views/blazer/queries/home.html.erb b/app/views/blazer/queries/home.html.erb
index dbdd821..a272df8 100644
--- a/app/views/blazer/queries/home.html.erb
+++ b/app/views/blazer/queries/home.html.erb
@@ -26,6 +26,7 @@
<%= link_to t('.new_dashboard'), new_dashboard_path %>
<%= link_to t('.new_check'), new_check_path %>
<%= link_to t('.site'), Rails.application.routes.url_helpers.site_path(Site.first || Site.new) %>
+ <%= link_to t('.users'), Rails.application.routes.url_helpers.users_path %>
diff --git a/app/views/users/index.haml b/app/views/users/index.haml
new file mode 100644
index 0000000..c746bd1
--- /dev/null
+++ b/app/views/users/index.haml
@@ -0,0 +1,27 @@
+%section.w-100.min-vh-100.d-flex.align-items-center.justify-content-center
+ %div
+ %nav
+ = link_to t('.back'), root_path, class: 'btn btn-info mb-3'
+
+ %table.table
+ %thead
+ -# Esto no es HTML5 estándar pero al parecer funciona
+ = form_for @user do |f|
+ %tr
+ %td{ colspan: 3 }
+ = f.label :email, class: 'visually-hidden'
+ = f.email_field :email, class: 'form-control', placeholder: t('.email'), required: true
+ %td= f.submit t('.create'), class: 'btn btn-success'
+ %tr
+ %th= t('.email')
+ %th= t('.created_by')
+ %th= t('.created')
+ %th= t('.actions')
+ %tbody
+
+ - @users.each do |user|
+ %tr
+ %th= user.email
+ %td= user.created_by.try :email
+ %td.text-center= user.created.count
+ %td= link_to t('.destroy'), user_path(user), method: :delete, class: 'btn btn-danger', data: { confirm: t('.confirm') }
diff --git a/config/locales/es.yml b/config/locales/es.yml
index 03857ea..f909087 100644
--- a/config/locales/es.yml
+++ b/config/locales/es.yml
@@ -39,4 +39,13 @@ es:
create: Guardar
part_of: Es parte de %{words}. Cualquier cambio puede afectarlas.
loading: Cargando...
-
+ users:
+ index:
+ email: Correo electrónico
+ create: Crear usuarix
+ destroy: Quitar acceso
+ confirm: ¿Confirmas?
+ back: Volver
+ actions: Acciones
+ created_by: Invitadx por
+ created: Invitadxs
diff --git a/db/migrate/20220611152100_add_created_by_to_users.rb b/db/migrate/20220611152100_add_created_by_to_users.rb
new file mode 100644
index 0000000..e496c56
--- /dev/null
+++ b/db/migrate/20220611152100_add_created_by_to_users.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+class AddCreatedByToUsers < ActiveRecord::Migration[6.1]
+ def change
+ add_belongs_to :users, :created_by, index: true
+ end
+end