ver artículos como invitade
This commit is contained in:
parent
847b798a82
commit
a125b388bb
15 changed files with 243 additions and 18 deletions
|
@ -23,6 +23,9 @@ class ApplicationController < ActionController::Base
|
|||
# lugar de desperdiciar una consulta
|
||||
current_usuarie.sites.find_by_name(id) ||
|
||||
current_usuarie.sites_as_invitade.find_by_name(id)
|
||||
|
||||
# TODO: reenviar a un 403 si el sitio ya no está permitido para le
|
||||
# usuarie
|
||||
end
|
||||
|
||||
def find_post(site)
|
||||
|
|
54
app/controllers/usuaries_controller.rb
Normal file
54
app/controllers/usuaries_controller.rb
Normal file
|
@ -0,0 +1,54 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
# Controlador de Usuaries
|
||||
class UsuariesController < ApplicationController
|
||||
include Pundit
|
||||
before_action :authenticate_usuarie!
|
||||
|
||||
# Mostrar todes les usuaries e invitades de un sitio
|
||||
def index
|
||||
@site = find_site
|
||||
site_usuarie = SiteUsuarie.new(@site, current_usuarie)
|
||||
authorize site_usuarie
|
||||
|
||||
@policy = policy(site_usuarie)
|
||||
end
|
||||
|
||||
# Desasociar une usuarie de un sitio
|
||||
def destroy
|
||||
@site = find_site
|
||||
authorize SiteUsuarie.new(@site, current_usuarie)
|
||||
|
||||
@usuarie = Usuarie.find(params[:id])
|
||||
|
||||
@usuarie.sites.delete(@site)
|
||||
|
||||
redirect_to site_usuaries_path
|
||||
end
|
||||
|
||||
# Convertir une usuarie en invitade
|
||||
def demote
|
||||
@site = find_site
|
||||
authorize SiteUsuarie.new(@site, current_usuarie)
|
||||
|
||||
@usuarie = Usuarie.find(params[:usuarie_id])
|
||||
|
||||
@usuarie.sites.delete(@site)
|
||||
@site.invitades << @usuarie
|
||||
|
||||
redirect_to site_usuaries_path
|
||||
end
|
||||
|
||||
# Convertir invitade en usuarie
|
||||
def promote
|
||||
@site = find_site
|
||||
authorize SiteUsuarie.new(@site, current_usuarie)
|
||||
|
||||
@usuarie = Usuarie.find(params[:usuarie_id])
|
||||
|
||||
@usuarie.sites_as_invitade.delete(@site)
|
||||
@site.usuaries << @usuarie
|
||||
|
||||
redirect_to site_usuaries_path
|
||||
end
|
||||
end
|
12
app/models/site_usuarie.rb
Normal file
12
app/models/site_usuarie.rb
Normal file
|
@ -0,0 +1,12 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
# Clase genérica a través de la que podemos obtener la relación entre
|
||||
# sitio y usuarie
|
||||
class SiteUsuarie
|
||||
attr_reader :site, :usuarie
|
||||
|
||||
def initialize(site, usuarie)
|
||||
@site = site
|
||||
@usuarie = usuarie
|
||||
end
|
||||
end
|
|
@ -9,6 +9,7 @@ class Usuarie < ApplicationRecord
|
|||
validates_uniqueness_of :email
|
||||
|
||||
has_and_belongs_to_many :sites
|
||||
has_and_belongs_to_many :sites_as_invitade, class_name: 'Site',
|
||||
join_table: 'invitades_sites'
|
||||
has_and_belongs_to_many :sites_as_invitade,
|
||||
class_name: 'Site',
|
||||
join_table: 'invitades_sites'
|
||||
end
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
#
|
||||
# TODO: Implementar Invitadx
|
||||
class PostPolicy
|
||||
attr_reader :post
|
||||
attr_reader :post, :usuarie
|
||||
|
||||
def initialize(usuarie, post)
|
||||
@usuarie = usuarie
|
||||
|
@ -17,7 +17,7 @@ class PostPolicy
|
|||
|
||||
# Lxs invitadxs solo pueden ver sus propios posts
|
||||
def show?
|
||||
true || post.author == usuarix.email
|
||||
post.site.usuarie?(usuarie) || post.author == usuarie.email
|
||||
end
|
||||
|
||||
def new?
|
||||
|
@ -34,7 +34,7 @@ class PostPolicy
|
|||
|
||||
# Lxs invitadxs solo pueden modificar sus propios artículos
|
||||
def update?
|
||||
true || post.author == usuarix.email
|
||||
post.site.usuarie?(usuarie) || post.author == usuarie.email
|
||||
end
|
||||
|
||||
# Solo las usuarias pueden eliminar artículos. Lxs invitadxs pueden
|
||||
|
@ -58,8 +58,8 @@ class PostPolicy
|
|||
#
|
||||
# Lxs invitadxs solo pueden ver sus propios posts
|
||||
def resolve
|
||||
# TODO: filtrar por invitade
|
||||
return scope
|
||||
return scope if scope.try(:first).try(:site).try(:usuarie?, usuarie)
|
||||
|
||||
# Asegurarse que al menos devolvemos []
|
||||
[scope.find do |post|
|
||||
post.author == usuarie.email
|
||||
|
|
35
app/policies/site_usuarie_policy.rb
Normal file
35
app/policies/site_usuarie_policy.rb
Normal file
|
@ -0,0 +1,35 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
# Gestiona la relación entre sitios y usuaries
|
||||
class SiteUsuariePolicy
|
||||
attr_reader :usuarie, :site_usuarie
|
||||
|
||||
def initialize(usuarie, site_usuarie)
|
||||
@usuarie = usuarie
|
||||
@site_usuarie = site_usuarie
|
||||
end
|
||||
|
||||
def index?
|
||||
usuarie?
|
||||
end
|
||||
|
||||
# Les usuaries pueden remover a otres usuaries e invitades del sitio
|
||||
def destroy?
|
||||
usuarie?
|
||||
end
|
||||
|
||||
# Les usuaries pueden convertir a otres usuaries en invitades
|
||||
def demote?
|
||||
usuarie?
|
||||
end
|
||||
|
||||
def promote?
|
||||
usuarie?
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def usuarie?
|
||||
site_usuarie.site.usuarie? usuarie
|
||||
end
|
||||
end
|
|
@ -17,7 +17,7 @@
|
|||
= link_to t('posts.new_with_template', template: @site.templates.first.id.humanize),
|
||||
new_site_post_path(@site, lang: @lang, template: @site.templates.first.id),
|
||||
class: 'btn btn-success'
|
||||
- if policy(Post).usuaria?
|
||||
- if @site.usuarie? current_usuarie
|
||||
%button.btn.btn-success.dropdown-toggle.dropdown-toggle-split{data: { toggle: 'split' },
|
||||
aria: { haspopup: 'true', expanded: 'false' }}
|
||||
%span.sr-only= t('posts.dropdown')
|
||||
|
|
|
@ -33,6 +33,12 @@
|
|||
text: t('i18n.edit'),
|
||||
type: 'info',
|
||||
link: site_i18n_edit_path(site)
|
||||
- if policy(SiteUsuarie.new(site, current_usuarie)).index?
|
||||
= render 'layouts/btn_with_tooltip',
|
||||
tooltip: t('usuaries.index.help.self'),
|
||||
text: t('usuaries.index.title'),
|
||||
type: 'info',
|
||||
link: site_usuaries_path(site)
|
||||
- if policy(site).build?
|
||||
- if site.enqueued?
|
||||
= render 'layouts/btn_with_tooltip',
|
||||
|
|
50
app/views/usuaries/index.haml
Normal file
50
app/views/usuaries/index.haml
Normal file
|
@ -0,0 +1,50 @@
|
|||
.row
|
||||
.col
|
||||
= render 'layouts/breadcrumb',
|
||||
crumbs: [ link_to(t('sites.index'), sites_path),
|
||||
@site.name,
|
||||
link_to(t('posts.index'),
|
||||
site_usuaries_path(@site)) ]
|
||||
= render 'layouts/help', help: t('help.breadcrumbs')
|
||||
.row
|
||||
.col
|
||||
%h1= t('.title')
|
||||
|
||||
.row
|
||||
.col
|
||||
-# Una tabla de usuaries y otra de invitades, con acciones
|
||||
- %i[usuaries invitades].each do |u|
|
||||
%h2= t(".#{u.to_s}")
|
||||
%p= t(".help.#{u.to_s}")
|
||||
%table.table.table-striped.table-condensed
|
||||
%tbody
|
||||
- @site.send(u).each do |cuenta|
|
||||
%tr
|
||||
-# TODO: avatares
|
||||
%td= cuenta.email
|
||||
%td
|
||||
.btn-group{role: 'group', 'aria-label': t('.actions')}
|
||||
- if @policy.demote? && @site.usuarie?(cuenta)
|
||||
= link_to t('.demote.text'),
|
||||
site_usuarie_demote_path(@site, cuenta),
|
||||
class: 'btn btn-warning',
|
||||
data: { toggle: 'tooltip',
|
||||
confirm: t('.demote.confirm')},
|
||||
title: t('.help.demote'),
|
||||
method: :patch
|
||||
- if @policy.promote? && @site.invitade?(cuenta)
|
||||
= link_to t('.promote.text'),
|
||||
site_usuarie_promote_path(@site, cuenta),
|
||||
class: 'btn btn-success',
|
||||
data: { toggle: 'tooltip',
|
||||
confirm: t('.promote.confirm')},
|
||||
title: t('.help.promote'),
|
||||
method: :patch
|
||||
- if @policy.destroy?
|
||||
= link_to t('.destroy.text'),
|
||||
site_usuarie_path(@site, cuenta),
|
||||
class: 'btn btn-danger',
|
||||
data: { toggle: 'tooltip',
|
||||
confirm: t('.destroy.confirm')},
|
||||
title: t('.help.destroy'),
|
||||
method: :delete
|
|
@ -258,3 +258,24 @@ en:
|
|||
blank: Nothing
|
||||
destroy: Delete
|
||||
confirm_destroy: Are you sure?
|
||||
usuaries:
|
||||
index:
|
||||
help:
|
||||
self: Self-manage who has access to this site
|
||||
destroy: Remove access to this site
|
||||
usuaries: 'Users can self-manage every section and option of this site, posts, review and approve posts from guests, publish changes, etc.'
|
||||
invitades: 'Guests can only create new posts and edit those authored by them. Any change needs review and approval by a user.'
|
||||
demote: Removes privileges for this user
|
||||
promote: Gives privileges to this guest
|
||||
title: Users and Guests
|
||||
usuaries: Users
|
||||
invitades: Guests
|
||||
destroy:
|
||||
text: 'Remove access'
|
||||
confirm: "Remove access to this site? The account itself is not deleted, but it won't be able to make changes to this site."
|
||||
demote:
|
||||
text: 'Convert to guest'
|
||||
confirm: 'Convert to guest? They can only edit their own posts and will need approval from other user to publish them.'
|
||||
promote:
|
||||
text: 'Convert to user'
|
||||
confirm: 'Convert to user? They will gain full access to self-manage this site.'
|
||||
|
|
|
@ -265,3 +265,24 @@ es:
|
|||
blank: En blanco
|
||||
destroy: Borrar
|
||||
confirm_destroy: ¿Estás segurx?
|
||||
usuaries:
|
||||
index:
|
||||
help:
|
||||
self: Gestionar quiénes tienen acceso a este sitio
|
||||
destroy: Impide el acceso a la gestión del sitio
|
||||
usuaries: 'Les usuaries pueden gestionar todas las secciones del sitio, crear artículos, revisar y aprobar artículos de invitades, publicar los cambios, etc.'
|
||||
invitades: 'Les invitades sólo pueden crear artículos nuevos y modificar los que cargaron. Todos los cambios que hagan necesitan la revisión y aprobación de une usuarie.'
|
||||
demote: Quita privilegios a este usuarie
|
||||
promote: Otorga privilegios a este invitade
|
||||
title: Usuaries e invitades
|
||||
usuaries: Usuaries
|
||||
invitades: Invitades
|
||||
destroy:
|
||||
text: 'Quitar acceso'
|
||||
confirm: '¿Quitar acceso a este sitio? La cuenta no será modificada, solo no podrá hacer cambios en este sitio.'
|
||||
demote:
|
||||
text: 'Convertir en invitade'
|
||||
confirm: '¿Convertir en invitade? Solo tendrá acceso a sus propios artículos y necesitará la aprobación de otre usuarie para publicarlos.'
|
||||
promote:
|
||||
text: 'Convertir en usuarie'
|
||||
confirm: '¿Convertir en usuarie? Ganará acceso a la gestión completa del sitio.'
|
||||
|
|
|
@ -16,16 +16,21 @@ Rails.application.routes.draw do
|
|||
|
||||
get 'public/:type/:basename', to: 'sites#send_public_file'
|
||||
|
||||
resources :posts
|
||||
resources :templates
|
||||
resources :invitadxs, only: %i[index new show] do
|
||||
get :confirmation, to: 'invitadxs#confirmation'
|
||||
# Gestionar usuaries
|
||||
resources :usuaries do
|
||||
patch 'demote', to: 'usuaries#demote'
|
||||
patch 'promote', to: 'usuaries#promote'
|
||||
end
|
||||
|
||||
# Gestionar artículos
|
||||
resources :posts
|
||||
|
||||
# Gestionar traducciones
|
||||
get 'i18n', to: 'i18n#index'
|
||||
get 'i18n/edit', to: 'i18n#edit'
|
||||
post 'i18n', to: 'i18n#update'
|
||||
|
||||
# Compilar el sitio
|
||||
post 'enqueue', to: 'sites#enqueue'
|
||||
get 'build_log', to: 'sites#build_log'
|
||||
post 'reorder_posts', to: 'sites#reorder_posts'
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
# Agrega índices únicos a la combinación de Usuarie y Site para no tener
|
||||
# accesos duplicados.
|
||||
class AddUniqueToInvitadesAndUsuaries < ActiveRecord::Migration[5.2]
|
||||
def change
|
||||
%i[invitades_sites sites_usuaries].each do |t|
|
||||
remove_index t, :site_id
|
||||
remove_index t, :usuarie_id
|
||||
add_index t, %i[site_id usuarie_id], unique: true
|
||||
end
|
||||
end
|
||||
end
|
|
@ -12,12 +12,11 @@
|
|||
#
|
||||
# It's strongly recommended that you check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema.define(version: 20_190_703_200_455) do
|
||||
ActiveRecord::Schema.define(version: 20_190_705_195_758) do
|
||||
create_table 'invitades_sites', id: false, force: :cascade do |t|
|
||||
t.integer 'site_id'
|
||||
t.integer 'usuarie_id'
|
||||
t.index ['site_id'], name: 'index_invitades_sites_on_site_id'
|
||||
t.index ['usuarie_id'], name: 'index_invitades_sites_on_usuarie_id'
|
||||
t.index %w[site_id usuarie_id], name: 'index_invitades_sites_on_site_id_and_usuarie_id', unique: true
|
||||
end
|
||||
|
||||
create_table 'sites', force: :cascade do |t|
|
||||
|
@ -30,8 +29,7 @@ ActiveRecord::Schema.define(version: 20_190_703_200_455) do
|
|||
create_table 'sites_usuaries', id: false, force: :cascade do |t|
|
||||
t.integer 'site_id'
|
||||
t.integer 'usuarie_id'
|
||||
t.index ['site_id'], name: 'index_sites_usuaries_on_site_id'
|
||||
t.index ['usuarie_id'], name: 'index_sites_usuaries_on_usuarie_id'
|
||||
t.index %w[site_id usuarie_id], name: 'index_sites_usuaries_on_site_id_and_usuarie_id', unique: true
|
||||
end
|
||||
|
||||
create_table 'usuaries', force: :cascade do |t|
|
||||
|
|
|
@ -36,4 +36,10 @@ De lo contrario necesitamos establecer roles y ya entramos en las
|
|||
dificultades que decíamos más arriba.
|
||||
|
||||
No podemos saber desde cuándo se creo la relación, a menos que tengamos
|
||||
una tabla de actividades.
|
||||
una tabla de actividades por separado.
|
||||
|
||||
Podemos saber quién es invitade ingresando a un sitio y fijándonos si
|
||||
está en su lista de invitade. Lo mismo para usuaries.
|
||||
|
||||
Les usuaries pueden bloquear invitades y a otres usuaries, y sumar
|
||||
usuaries e invitades a su sitio (via correo de invitación).
|
||||
|
|
Loading…
Reference in a new issue