mirror of
https://0xacab.org/sutty/sutty
synced 2024-11-15 02:31:42 +00:00
gestionar usuaries de un sitio
This commit is contained in:
parent
a125b388bb
commit
64fcf61c67
22 changed files with 348 additions and 5 deletions
|
@ -19,6 +19,7 @@ Metrics/AbcSize:
|
||||||
- 'app/controllers/posts_controller.rb'
|
- 'app/controllers/posts_controller.rb'
|
||||||
- 'app/controllers/invitadxs_controller.rb'
|
- 'app/controllers/invitadxs_controller.rb'
|
||||||
- 'app/controllers/i18n_controller.rb'
|
- 'app/controllers/i18n_controller.rb'
|
||||||
|
- 'app/controllers/usuaries_controller.rb'
|
||||||
|
|
||||||
Metrics/MethodLength:
|
Metrics/MethodLength:
|
||||||
Exclude:
|
Exclude:
|
||||||
|
|
1
Gemfile
1
Gemfile
|
@ -41,6 +41,7 @@ gem 'carrierwave-i18n'
|
||||||
gem 'commonmarker'
|
gem 'commonmarker'
|
||||||
gem 'devise'
|
gem 'devise'
|
||||||
gem 'devise-i18n'
|
gem 'devise-i18n'
|
||||||
|
gem 'devise_invitable'
|
||||||
gem 'email_address'
|
gem 'email_address'
|
||||||
gem 'exception_notification'
|
gem 'exception_notification'
|
||||||
gem 'font-awesome-rails'
|
gem 'font-awesome-rails'
|
||||||
|
|
|
@ -106,6 +106,9 @@ GEM
|
||||||
warden (~> 1.2.3)
|
warden (~> 1.2.3)
|
||||||
devise-i18n (1.8.0)
|
devise-i18n (1.8.0)
|
||||||
devise (>= 4.6)
|
devise (>= 4.6)
|
||||||
|
devise_invitable (2.0.1)
|
||||||
|
actionmailer (>= 5.0)
|
||||||
|
devise (>= 4.6)
|
||||||
dotenv (2.7.2)
|
dotenv (2.7.2)
|
||||||
dotenv-rails (2.7.2)
|
dotenv-rails (2.7.2)
|
||||||
dotenv (= 2.7.2)
|
dotenv (= 2.7.2)
|
||||||
|
@ -363,6 +366,7 @@ DEPENDENCIES
|
||||||
commonmarker
|
commonmarker
|
||||||
devise
|
devise
|
||||||
devise-i18n
|
devise-i18n
|
||||||
|
devise_invitable
|
||||||
dotenv-rails
|
dotenv-rails
|
||||||
ed25519
|
ed25519
|
||||||
email_address
|
email_address
|
||||||
|
|
|
@ -51,4 +51,59 @@ class UsuariesController < ApplicationController
|
||||||
|
|
||||||
redirect_to site_usuaries_path
|
redirect_to site_usuaries_path
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Poder invitar
|
||||||
|
def invite
|
||||||
|
@site = find_site
|
||||||
|
site_usuarie = SiteUsuarie.new(@site, current_usuarie)
|
||||||
|
authorize site_usuarie
|
||||||
|
|
||||||
|
@policy = policy(site_usuarie)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Envía las invitaciones
|
||||||
|
def send_invitations
|
||||||
|
@site = find_site
|
||||||
|
authorize SiteUsuarie.new(@site, current_usuarie)
|
||||||
|
|
||||||
|
# Enviar la invitación si es necesario y agregar al sitio
|
||||||
|
#
|
||||||
|
# TODO: Pedir consentimiento para agregar a un sitio!
|
||||||
|
invitaciones.each do |invitacion|
|
||||||
|
# Si la cuenta no existe, envía una invitación por correo
|
||||||
|
usuarie = Usuarie.invite! email: invitacion.address
|
||||||
|
|
||||||
|
# No invitar al sitio si ya estaba en la lista!
|
||||||
|
unless @site.invitade?(usuarie) || @site.usuarie?(usuarie)
|
||||||
|
@site.send(invited_as) << usuarie
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
redirect_to site_usuaries_path(@site)
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
# Traer todas las invitaciones que al menos tengan usuarie y dominio
|
||||||
|
def invitaciones
|
||||||
|
# XXX: Podríamos usar EmailAddress pero hace chequeos más lentos
|
||||||
|
i = params[:invitaciones].split("\n").map do |m|
|
||||||
|
Mail::Address.new m
|
||||||
|
rescue Mail::Field::IncompleteParseError
|
||||||
|
nil
|
||||||
|
end.compact
|
||||||
|
|
||||||
|
i.select do |m|
|
||||||
|
m.local && m.domain
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# El tipo de invitación que tenemos que enviar, si alguien mandó
|
||||||
|
# cualquier cosa, usamos el privilegio menor.
|
||||||
|
def invited_as
|
||||||
|
invited_as = params[:invited_as].try(:to_sym)
|
||||||
|
invited_as = :invitades unless %i[usuaries invitades].include?(invited_as)
|
||||||
|
|
||||||
|
invited_as
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
# Usuarie de la plataforma
|
# Usuarie de la plataforma
|
||||||
class Usuarie < ApplicationRecord
|
class Usuarie < ApplicationRecord
|
||||||
devise :database_authenticatable,
|
devise :invitable, :database_authenticatable,
|
||||||
:recoverable, :rememberable, :validatable,
|
:recoverable, :rememberable, :validatable,
|
||||||
:confirmable, :lockable, :registerable
|
:confirmable, :lockable, :registerable
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,14 @@ class SiteUsuariePolicy
|
||||||
usuarie?
|
usuarie?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def invite?
|
||||||
|
usuarie?
|
||||||
|
end
|
||||||
|
|
||||||
|
def send_invitations?
|
||||||
|
usuarie?
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def usuarie?
|
def usuarie?
|
||||||
|
|
16
app/views/devise/invitations/edit.haml
Normal file
16
app/views/devise/invitations/edit.haml
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
.row.align-items-center.justify-content-center.full-height
|
||||||
|
.col-md-6.align-self-center
|
||||||
|
%h2= t 'devise.invitations.edit.header'
|
||||||
|
= form_for(resource, as: resource_name, url: invitation_path(resource_name), html: { method: :put }) do |f|
|
||||||
|
= render 'devise/shared/error_messages', resource: resource
|
||||||
|
= f.hidden_field :invitation_token, readonly: true
|
||||||
|
- if f.object.class.require_password_on_accepting
|
||||||
|
.form-group
|
||||||
|
= f.label :password
|
||||||
|
= f.password_field :password, class: 'form-control'
|
||||||
|
.form-group
|
||||||
|
= f.label :password_confirmation
|
||||||
|
= f.password_field :password_confirmation, class: 'form-control'
|
||||||
|
.actions
|
||||||
|
= f.submit t('devise.invitations.edit.submit_button'),
|
||||||
|
class: 'btn btn-lg btn-primary btn-block'
|
12
app/views/devise/invitations/new.haml
Normal file
12
app/views/devise/invitations/new.haml
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
.row.align-items-center.justify-content-center.full-height
|
||||||
|
.col-md-6.align-self-center
|
||||||
|
%h2= t 'devise.invitations.new.header'
|
||||||
|
= form_for(resource, as: resource_name, url: invitation_path(resource_name), html: { method: :post }) do |f|
|
||||||
|
= render 'devise/shared/error_messages', resource: resource
|
||||||
|
- resource.class.invite_key_fields.each do |field|
|
||||||
|
.form-group
|
||||||
|
= f.label field
|
||||||
|
= f.text_field field, class: 'form-control'
|
||||||
|
.actions
|
||||||
|
= f.submit t('devise.invitations.new.submit_button'),
|
||||||
|
class: 'btn btn-lg btn-primary btn-block'
|
6
app/views/devise/mailer/invitation_instructions.haml
Normal file
6
app/views/devise/mailer/invitation_instructions.haml
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
%p= t("devise.mailer.invitation_instructions.hello", email: @resource.email)
|
||||||
|
%p= t("devise.mailer.invitation_instructions.someone_invited_you", url: root_url)
|
||||||
|
%p= link_to t("devise.mailer.invitation_instructions.accept"), accept_invitation_url(@resource, invitation_token: @token)
|
||||||
|
- if @resource.invitation_due_at
|
||||||
|
%p= t("devise.mailer.invitation_instructions.accept_until", due_date: l(@resource.invitation_due_at, format: :'devise.mailer.invitation_instructions.accept_until_format'))
|
||||||
|
%p= t("devise.mailer.invitation_instructions.ignore")
|
|
@ -0,0 +1,6 @@
|
||||||
|
= t("devise.mailer.invitation_instructions.hello", email: @resource.email)
|
||||||
|
= t("devise.mailer.invitation_instructions.someone_invited_you", url: root_url)
|
||||||
|
= accept_invitation_url(@resource, invitation_token: @token)
|
||||||
|
- if @resource.invitation_due_at
|
||||||
|
= t("devise.mailer.invitation_instructions.accept_until", due_date: l(@resource.invitation_due_at, format: :'devise.mailer.invitation_instructions.accept_until_format'))
|
||||||
|
= t("devise.mailer.invitation_instructions.ignore")
|
|
@ -1 +0,0 @@
|
||||||
<%= yield %>
|
|
|
@ -14,7 +14,15 @@
|
||||||
.col
|
.col
|
||||||
-# Una tabla de usuaries y otra de invitades, con acciones
|
-# Una tabla de usuaries y otra de invitades, con acciones
|
||||||
- %i[usuaries invitades].each do |u|
|
- %i[usuaries invitades].each do |u|
|
||||||
%h2= t(".#{u.to_s}")
|
%h2
|
||||||
|
= t(".#{u.to_s}")
|
||||||
|
.btn-group{role: 'group', 'aria-label': t('.actions')}
|
||||||
|
- if @policy.invite?
|
||||||
|
= link_to t('.invite.text'),
|
||||||
|
site_usuaries_invite_path(@site, invite_as: u.to_s),
|
||||||
|
class: 'btn btn-success',
|
||||||
|
data: { toggle: 'tooltip' },
|
||||||
|
title: t('.help.invite', invite_as: u.to_s)
|
||||||
%p= t(".help.#{u.to_s}")
|
%p= t(".help.#{u.to_s}")
|
||||||
%table.table.table-striped.table-condensed
|
%table.table.table-striped.table-condensed
|
||||||
%tbody
|
%tbody
|
||||||
|
@ -23,7 +31,7 @@
|
||||||
-# TODO: avatares
|
-# TODO: avatares
|
||||||
%td= cuenta.email
|
%td= cuenta.email
|
||||||
%td
|
%td
|
||||||
.btn-group{role: 'group', 'aria-label': t('.actions')}
|
.btn-group{role: 'group', 'aria-label': t('.individual_actions')}
|
||||||
- if @policy.demote? && @site.usuarie?(cuenta)
|
- if @policy.demote? && @site.usuarie?(cuenta)
|
||||||
= link_to t('.demote.text'),
|
= link_to t('.demote.text'),
|
||||||
site_usuarie_demote_path(@site, cuenta),
|
site_usuarie_demote_path(@site, cuenta),
|
||||||
|
|
26
app/views/usuaries/invite.haml
Normal file
26
app/views/usuaries/invite.haml
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
- invite_as = t("usuaries.invite_as.#{params[:invite_as]}")
|
||||||
|
.row
|
||||||
|
.col
|
||||||
|
= render 'layouts/breadcrumb',
|
||||||
|
crumbs: [ link_to(t('sites.index'), sites_path),
|
||||||
|
@site.name,
|
||||||
|
link_to(t('posts.index'),
|
||||||
|
site_usuaries_path(@site)),
|
||||||
|
t('.title', invite_as: invite_as) ]
|
||||||
|
= render 'layouts/help', help: t('help.breadcrumbs')
|
||||||
|
.row
|
||||||
|
.col
|
||||||
|
%h1= t('.title', invite_as: invite_as)
|
||||||
|
|
||||||
|
.row
|
||||||
|
.col
|
||||||
|
= form_with url: site_usuaries_invite_path(@site) do |f|
|
||||||
|
= f.hidden_field :invite_as, value: params[:invite_as]
|
||||||
|
.form-group
|
||||||
|
= f.label :invitaciones do
|
||||||
|
= t('.invitaciones')
|
||||||
|
%small.text-muted.form-text= t('.help.invitaciones',
|
||||||
|
invite_as: invite_as)
|
||||||
|
= f.text_area :invitaciones, class: 'form-control'
|
||||||
|
.form-group
|
||||||
|
= f.submit t('.submit'), class: 'btn btn-success'
|
|
@ -136,6 +136,58 @@ Devise.setup do |config|
|
||||||
# Send a notification email when the user's password is changed.
|
# Send a notification email when the user's password is changed.
|
||||||
config.send_password_change_notification = true
|
config.send_password_change_notification = true
|
||||||
|
|
||||||
|
# ==> Configuration for :invitable
|
||||||
|
# The period the generated invitation token is valid. After this
|
||||||
|
# period, the invited resource won't be able to accept the invitation.
|
||||||
|
# When invite_for is 0 (the default), the invitation won't expire.
|
||||||
|
config.invite_for = 2.weeks
|
||||||
|
|
||||||
|
# Number of invitations users can send.
|
||||||
|
# - If invitation_limit is nil, there is no limit for invitations,
|
||||||
|
# users can send unlimited invitations, invitation_limit column is not
|
||||||
|
# used.
|
||||||
|
# - If invitation_limit is 0, users can't send invitations by default.
|
||||||
|
# - If invitation_limit n > 0, users can send n invitations.
|
||||||
|
# You can change invitation_limit column for some users so they can
|
||||||
|
# send more or less invitations, even with global invitation_limit = 0
|
||||||
|
# Default: nil
|
||||||
|
config.invitation_limit = 0
|
||||||
|
|
||||||
|
# The key to be used to check existing users when sending an
|
||||||
|
# invitation and the regexp used to test it when validate_on_invite is
|
||||||
|
# not set.
|
||||||
|
# config.invite_key = { email: /\A[^@]+@[^@]+\z/ }
|
||||||
|
# config.invite_key = { email: /\A[^@]+@[^@]+\z/, username: nil }
|
||||||
|
|
||||||
|
# Ensure that invited record is valid.
|
||||||
|
# The invitation won't be sent if this check fails.
|
||||||
|
# Default: false
|
||||||
|
# config.validate_on_invite = true
|
||||||
|
|
||||||
|
# Resend invitation if user with invited status is invited again
|
||||||
|
# Default: true
|
||||||
|
# config.resend_invitation = false
|
||||||
|
|
||||||
|
# The class name of the inviting model. If this is nil,
|
||||||
|
# the #invited_by association is declared to be polymorphic.
|
||||||
|
# Default: nil
|
||||||
|
# config.invited_by_class_name = 'User'
|
||||||
|
|
||||||
|
# The foreign key to the inviting model (if invited_by_class_name is
|
||||||
|
# set)
|
||||||
|
# Default: :invited_by_id
|
||||||
|
# config.invited_by_foreign_key = :invited_by_id
|
||||||
|
|
||||||
|
# The column name used for counter_cache column. If this is nil,
|
||||||
|
# the #invited_by association is declared without counter_cache.
|
||||||
|
# Default: nil
|
||||||
|
# config.invited_by_counter_cache = :invitations_count
|
||||||
|
|
||||||
|
# Auto-login after the user accepts the invite. If this is false,
|
||||||
|
# the user will need to manually log in after accepting the invite.
|
||||||
|
# Default: true
|
||||||
|
# config.allow_insecure_sign_in_after_accept = false
|
||||||
|
|
||||||
# ==> Configuration for :confirmable
|
# ==> Configuration for :confirmable
|
||||||
# A period that the user is allowed to access the website even without
|
# A period that the user is allowed to access the website even without
|
||||||
# confirming their account. For instance, if set to 2.days, the user
|
# confirming their account. For instance, if set to 2.days, the user
|
||||||
|
|
31
config/locales/devise_invitable.en.yml
Normal file
31
config/locales/devise_invitable.en.yml
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
en:
|
||||||
|
devise:
|
||||||
|
failure:
|
||||||
|
invited: "You have a pending invitation, accept it to finish creating your account."
|
||||||
|
invitations:
|
||||||
|
send_instructions: "An invitation email has been sent to %{email}."
|
||||||
|
invitation_token_invalid: "The invitation token provided is not valid!"
|
||||||
|
updated: "Your password was set successfully. You are now signed in."
|
||||||
|
updated_not_active: "Your password was set successfully."
|
||||||
|
no_invitations_remaining: "No invitations remaining"
|
||||||
|
invitation_removed: "Your invitation was removed."
|
||||||
|
new:
|
||||||
|
header: "Send invitation"
|
||||||
|
submit_button: "Send an invitation"
|
||||||
|
edit:
|
||||||
|
header: "Set your password"
|
||||||
|
submit_button: "Set my password"
|
||||||
|
mailer:
|
||||||
|
invitation_instructions:
|
||||||
|
subject: "Invitation instructions"
|
||||||
|
hello: "Hello %{email}"
|
||||||
|
someone_invited_you: "Someone has invited you to %{url}, you can accept it through the link below."
|
||||||
|
accept: "Accept invitation"
|
||||||
|
accept_until: "This invitation will be due in %{due_date}."
|
||||||
|
ignore: "If you don't want to accept the invitation, please ignore this email. Your account won't be created until you access the link above and set your password."
|
||||||
|
time:
|
||||||
|
formats:
|
||||||
|
devise:
|
||||||
|
mailer:
|
||||||
|
invitation_instructions:
|
||||||
|
accept_until_format: "%B %d, %Y %I:%M %p"
|
31
config/locales/devise_invitable.es.yml
Normal file
31
config/locales/devise_invitable.es.yml
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
es:
|
||||||
|
devise:
|
||||||
|
failure:
|
||||||
|
invited: "Tenés una invitación pendiente, aceptala para terminar de crear tu cuenta."
|
||||||
|
invitations:
|
||||||
|
send_instructions: "Hemos enviado una invitación a %{email}."
|
||||||
|
invitation_token_invalid: "¡El código de invitación no es válido!"
|
||||||
|
updated: "Configuraste tu contraseña correctamente, a partir de ahora podés ingresar."
|
||||||
|
updated_not_active: "Configuraste tu contraseña correctamente."
|
||||||
|
no_invitations_remaining: "No te quedan invitaciones"
|
||||||
|
invitation_removed: "La invitación ha sido eliminada."
|
||||||
|
new:
|
||||||
|
header: "Invitar a alguien"
|
||||||
|
submit_button: "Enviar la invitación"
|
||||||
|
edit:
|
||||||
|
header: "Configura tu contraseña"
|
||||||
|
submit_button: "Configurar mi contraseña"
|
||||||
|
mailer:
|
||||||
|
invitation_instructions:
|
||||||
|
subject: "Invitación"
|
||||||
|
hello: "Hola %{email}"
|
||||||
|
someone_invited_you: "Alguien te ha invitado a colaborar en %{url}, podés aceptar la invitación con el enlace a continuación."
|
||||||
|
accept: "Aceptar la invitación"
|
||||||
|
accept_until: "La invitación vencerá en %{due_date}."
|
||||||
|
ignore: "Si no querés aceptar la invitación, por favor ignora este correo. Tu cuenta no será creada hasta que aceptes la invitación y configures una contraseña."
|
||||||
|
time:
|
||||||
|
formats:
|
||||||
|
devise:
|
||||||
|
mailer:
|
||||||
|
invitation_instructions:
|
||||||
|
accept_until_format: "%d/%m/%Y a las %H:%M"
|
|
@ -259,6 +259,9 @@ en:
|
||||||
destroy: Delete
|
destroy: Delete
|
||||||
confirm_destroy: Are you sure?
|
confirm_destroy: Are you sure?
|
||||||
usuaries:
|
usuaries:
|
||||||
|
invite_as:
|
||||||
|
usuaries: users
|
||||||
|
invitades: guests
|
||||||
index:
|
index:
|
||||||
help:
|
help:
|
||||||
self: Self-manage who has access to this site
|
self: Self-manage who has access to this site
|
||||||
|
@ -267,6 +270,7 @@ en:
|
||||||
invitades: 'Guests can only create new posts and edit those authored by them. Any change needs review and approval by a user.'
|
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
|
demote: Removes privileges for this user
|
||||||
promote: Gives privileges to this guest
|
promote: Gives privileges to this guest
|
||||||
|
invite: 'Invites %{invite_as} to this site'
|
||||||
title: Users and Guests
|
title: Users and Guests
|
||||||
usuaries: Users
|
usuaries: Users
|
||||||
invitades: Guests
|
invitades: Guests
|
||||||
|
@ -279,3 +283,11 @@ en:
|
||||||
promote:
|
promote:
|
||||||
text: 'Convert to user'
|
text: 'Convert to user'
|
||||||
confirm: 'Convert to user? They will gain full access to self-manage this site.'
|
confirm: 'Convert to user? They will gain full access to self-manage this site.'
|
||||||
|
invite:
|
||||||
|
text: 'Invite'
|
||||||
|
invite:
|
||||||
|
title: 'Invite %{invite_as}'
|
||||||
|
help:
|
||||||
|
invitaciones: 'You can invite new %{invite_as} by entering an email address per line. They will receive an email with your invitation and decide if they want to accept or not.'
|
||||||
|
invitaciones: Send invitations to these addresses
|
||||||
|
submit: Send invitations
|
||||||
|
|
|
@ -266,6 +266,9 @@ es:
|
||||||
destroy: Borrar
|
destroy: Borrar
|
||||||
confirm_destroy: ¿Estás segurx?
|
confirm_destroy: ¿Estás segurx?
|
||||||
usuaries:
|
usuaries:
|
||||||
|
invite_as:
|
||||||
|
usuaries: usuaries
|
||||||
|
invitades: invitades
|
||||||
index:
|
index:
|
||||||
help:
|
help:
|
||||||
self: Gestionar quiénes tienen acceso a este sitio
|
self: Gestionar quiénes tienen acceso a este sitio
|
||||||
|
@ -274,6 +277,7 @@ es:
|
||||||
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.'
|
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
|
demote: Quita privilegios a este usuarie
|
||||||
promote: Otorga privilegios a este invitade
|
promote: Otorga privilegios a este invitade
|
||||||
|
invite: 'Invita %{invite_as} a colaborar en este sitio'
|
||||||
title: Usuaries e invitades
|
title: Usuaries e invitades
|
||||||
usuaries: Usuaries
|
usuaries: Usuaries
|
||||||
invitades: Invitades
|
invitades: Invitades
|
||||||
|
@ -286,3 +290,11 @@ es:
|
||||||
promote:
|
promote:
|
||||||
text: 'Convertir en usuarie'
|
text: 'Convertir en usuarie'
|
||||||
confirm: '¿Convertir en usuarie? Ganará acceso a la gestión completa del sitio.'
|
confirm: '¿Convertir en usuarie? Ganará acceso a la gestión completa del sitio.'
|
||||||
|
invite:
|
||||||
|
text: 'Invitar'
|
||||||
|
invite:
|
||||||
|
title: 'Invitar %{invite_as}'
|
||||||
|
help:
|
||||||
|
invitaciones: 'Invita nueves %{invite_as} ingresando una dirección de correo electrónico por línea. Recibirán un correo con tu invitación y podrán aceptarla o no.'
|
||||||
|
invitaciones: Invitar a estas direcciones
|
||||||
|
submit: Enviar invitaciones
|
||||||
|
|
|
@ -17,6 +17,8 @@ Rails.application.routes.draw do
|
||||||
get 'public/:type/:basename', to: 'sites#send_public_file'
|
get 'public/:type/:basename', to: 'sites#send_public_file'
|
||||||
|
|
||||||
# Gestionar usuaries
|
# Gestionar usuaries
|
||||||
|
get 'usuaries/invite', to: 'usuaries#invite'
|
||||||
|
post 'usuaries/invite', to: 'usuaries#send_invitations'
|
||||||
resources :usuaries do
|
resources :usuaries do
|
||||||
patch 'demote', to: 'usuaries#demote'
|
patch 'demote', to: 'usuaries#demote'
|
||||||
patch 'promote', to: 'usuaries#promote'
|
patch 'promote', to: 'usuaries#promote'
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
# Agregar gestión de invitaciones a usuaries
|
||||||
|
class DeviseInvitableAddToUsuaries < ActiveRecord::Migration[5.2]
|
||||||
|
def up
|
||||||
|
change_table :usuaries do |t|
|
||||||
|
t.string :invitation_token
|
||||||
|
t.datetime :invitation_created_at
|
||||||
|
t.datetime :invitation_sent_at
|
||||||
|
t.datetime :invitation_accepted_at
|
||||||
|
t.integer :invitation_limit
|
||||||
|
t.references :invited_by, polymorphic: true
|
||||||
|
t.integer :invitations_count, default: 0
|
||||||
|
t.index :invitations_count
|
||||||
|
t.index :invitation_token, unique: true # for invitable
|
||||||
|
t.index :invited_by_id
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def down
|
||||||
|
change_table :usuaries do |t|
|
||||||
|
t.remove_references :invited_by, polymorphic: true
|
||||||
|
t.remove :invitations_count, :invitation_limit, :invitation_sent_at, :invitation_accepted_at, :invitation_token, :invitation_created_at
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
14
db/schema.rb
14
db/schema.rb
|
@ -12,7 +12,7 @@
|
||||||
#
|
#
|
||||||
# It's strongly recommended that you check this file into your version control system.
|
# It's strongly recommended that you check this file into your version control system.
|
||||||
|
|
||||||
ActiveRecord::Schema.define(version: 20_190_705_195_758) do
|
ActiveRecord::Schema.define(version: 20_190_705_215_536) do
|
||||||
create_table 'invitades_sites', id: false, force: :cascade do |t|
|
create_table 'invitades_sites', id: false, force: :cascade do |t|
|
||||||
t.integer 'site_id'
|
t.integer 'site_id'
|
||||||
t.integer 'usuarie_id'
|
t.integer 'usuarie_id'
|
||||||
|
@ -48,8 +48,20 @@ ActiveRecord::Schema.define(version: 20_190_705_195_758) do
|
||||||
t.string 'unlock_token'
|
t.string 'unlock_token'
|
||||||
t.datetime 'locked_at'
|
t.datetime 'locked_at'
|
||||||
t.boolean 'acepta_politicas_de_privacidad', default: false
|
t.boolean 'acepta_politicas_de_privacidad', default: false
|
||||||
|
t.string 'invitation_token'
|
||||||
|
t.datetime 'invitation_created_at'
|
||||||
|
t.datetime 'invitation_sent_at'
|
||||||
|
t.datetime 'invitation_accepted_at'
|
||||||
|
t.integer 'invitation_limit'
|
||||||
|
t.string 'invited_by_type'
|
||||||
|
t.integer 'invited_by_id'
|
||||||
|
t.integer 'invitations_count', default: 0
|
||||||
t.index ['confirmation_token'], name: 'index_usuaries_on_confirmation_token', unique: true
|
t.index ['confirmation_token'], name: 'index_usuaries_on_confirmation_token', unique: true
|
||||||
t.index ['email'], name: 'index_usuaries_on_email', unique: true
|
t.index ['email'], name: 'index_usuaries_on_email', unique: true
|
||||||
|
t.index ['invitation_token'], name: 'index_usuaries_on_invitation_token', unique: true
|
||||||
|
t.index ['invitations_count'], name: 'index_usuaries_on_invitations_count'
|
||||||
|
t.index ['invited_by_id'], name: 'index_usuaries_on_invited_by_id'
|
||||||
|
t.index %w[invited_by_type invited_by_id], name: 'index_usuaries_on_invited_by_type_and_invited_by_id'
|
||||||
t.index ['reset_password_token'], name: 'index_usuaries_on_reset_password_token', unique: true
|
t.index ['reset_password_token'], name: 'index_usuaries_on_reset_password_token', unique: true
|
||||||
t.index ['unlock_token'], name: 'index_usuaries_on_unlock_token', unique: true
|
t.index ['unlock_token'], name: 'index_usuaries_on_unlock_token', unique: true
|
||||||
end
|
end
|
||||||
|
|
|
@ -43,3 +43,26 @@ está en su lista de invitade. Lo mismo para usuaries.
|
||||||
|
|
||||||
Les usuaries pueden bloquear invitades y a otres usuaries, y sumar
|
Les usuaries pueden bloquear invitades y a otres usuaries, y sumar
|
||||||
usuaries e invitades a su sitio (via correo de invitación).
|
usuaries e invitades a su sitio (via correo de invitación).
|
||||||
|
|
||||||
|
## Invitaciones a sitios
|
||||||
|
|
||||||
|
### Enviar invitación
|
||||||
|
|
||||||
|
Desde la gestión del sitio se puede invitar a nueves usuaries e
|
||||||
|
invitades. Se les envía un correo (y cuando tengamos sistema de
|
||||||
|
notificaciones, una notificación) donde pueden confirmar su
|
||||||
|
participación.
|
||||||
|
|
||||||
|
Si no tienen cuenta, tienen que registrarse completando los datos en el
|
||||||
|
momento, sino se pueden loguear normalmente.
|
||||||
|
|
||||||
|
Si ya están logueades, se acepta la invitación inmediatamente.
|
||||||
|
|
||||||
|
### Invitades desde la web
|
||||||
|
|
||||||
|
Al publicar la URL de invitación, les invitades se puedan registrar
|
||||||
|
por su cuenta. Solo deben completar sus datos (correo y contraseña) y
|
||||||
|
reciben un correo de confirmación.
|
||||||
|
|
||||||
|
En la configuración del sitio hay que distinguir entre invitades por
|
||||||
|
invitación o por registro automático.
|
||||||
|
|
Loading…
Reference in a new issue