diff --git a/app/controllers/sites_controller.rb b/app/controllers/sites_controller.rb index 6ca91f10..3f280dd9 100644 --- a/app/controllers/sites_controller.rb +++ b/app/controllers/sites_controller.rb @@ -14,12 +14,30 @@ class SitesController < ApplicationController # No tenemos propiedades de un sitio aún, así que vamos al listado de # artículos def show - authorize Site site = find_site + authorize site redirect_to site_posts_path(site) end + def new + @site = Site.new + authorize @site + end + + def create + @site = Site.new(site_params) + current_usuarie.roles << Rol.new(site: @site, + temporal: false, + rol: 'usuarie') + + if current_usuarie.save + redirect_to site_path(@site) + else + render 'new' + end + end + # Envía un archivo del directorio público de Jekyll def send_public_file authorize Site @@ -79,4 +97,10 @@ class SitesController < ApplicationController redirect_to site_posts_path @site end + + private + + def site_params + params.require(:site).permit(:name) + end end diff --git a/app/models/site.rb b/app/models/site.rb index da3838e5..00d14838 100644 --- a/app/models/site.rb +++ b/app/models/site.rb @@ -359,7 +359,7 @@ class Site < ApplicationRecord # Carga el sitio Jekyll def load_jekyll! - return unless name + return unless name.present? && File.directory?(path) Dir.chdir(path) do @jekyll ||= Site.load_jekyll(Dir.pwd) diff --git a/app/policies/site_policy.rb b/app/policies/site_policy.rb index 1042f521..900c8f53 100644 --- a/app/policies/site_policy.rb +++ b/app/policies/site_policy.rb @@ -16,13 +16,35 @@ class SitePolicy # Todes les usuaries pueden ver el sitio si aceptaron la invitación def show? - !@usuarie.rol_for_site(@site).temporal + !current_role.temporal + end + + # Todes pueden crear nuevos sitios + def new? + true + end + + def create? + new? + end + + # Para poder editarlos también tienen que haber aceptado la invitación + def edit? + show? && usuarie? + end + + def update? + edit? + end + + def destroy? + edit? end # Les invitades no pueden generar el sitio y les usuaries solo hasta # que aceptan la invitación def build? - show? && !site.invitade?(usuarie) + show? && usuarie? end def send_public_file? @@ -40,4 +62,18 @@ class SitePolicy def reorder_posts? build? end + + private + + def current_role + usuarie.rol_for_site(site) + end + + def usuarie? + site.usuarie? usuarie + end + + def invitade? + site.invitade? usuarie + end end diff --git a/app/views/layouts/_breadcrumb.haml b/app/views/layouts/_breadcrumb.haml index c8793762..01484ac6 100644 --- a/app/views/layouts/_breadcrumb.haml +++ b/app/views/layouts/_breadcrumb.haml @@ -5,7 +5,7 @@ data: { toggle: 'tooltip' }, title: t('help.logout'), role: 'button', class: 'btn-text' do = fa_icon 'sign-out', title: t('help.logout') - - if help = @site.try(:config).try(:dig, 'help') + - if @site.try(:persisted?) && (help = @site.try(:config).try(:dig, 'help')) %li.breadcrumb-item= link_to t('.help'), help, target: '_blank' - crumbs.compact.each do |crumb| - if current_user.is_a? Invitadx diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml index e5f5fc5f..384ce108 100644 --- a/app/views/layouts/application.html.haml +++ b/app/views/layouts/application.html.haml @@ -6,7 +6,7 @@ = csrf_meta_tags = stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' = javascript_include_tag 'application', 'data-turbolinks-track': 'reload' - - if @site.try(:config).try(:dig, 'css') + - if @site.try(:persisted?) && @site.try(:config).try(:dig, 'css') %link{rel: 'stylesheet', type: 'text/css', href: @site.get_url_from_site(@site.config.dig('css'))} - style = "background-image: url(#{@site.try(:cover) || image_url('background.jpg')})" %body{class: @has_cover ? 'background-cover' : '', style: @has_cover ? style : ''} diff --git a/app/views/sites/index.haml b/app/views/sites/index.haml index d953b8c5..b1085caa 100644 --- a/app/views/sites/index.haml +++ b/app/views/sites/index.haml @@ -4,7 +4,11 @@ = render 'layouts/breadcrumb', crumbs: [ t('sites.index') ] .row .col - %h1= t('sites.title') + %h1 + = t('sites.title') + - if policy(Site).new? + = link_to t('sites.new.title'), new_site_path, + class: 'btn btn-info' = render 'layouts/help', help: t('help.sites.index') diff --git a/app/views/sites/new.haml b/app/views/sites/new.haml new file mode 100644 index 00000000..2e28dcde --- /dev/null +++ b/app/views/sites/new.haml @@ -0,0 +1,14 @@ +.row + .col + = render 'layouts/breadcrumb', + crumbs: [ link_to(t('sites.index'), sites_path), t('.title') ] +.row + .col + %h1= t('.title') + + = form_for @site do |f| + .form-group + = f.label :name + = f.text_field :name, class: 'form-control' + .form-group + = f.submit t('.submit'), class: 'btn btn-success' diff --git a/config/initializers/devise.rb b/config/initializers/devise.rb index f7e7acdc..e3dce7c2 100644 --- a/config/initializers/devise.rb +++ b/config/initializers/devise.rb @@ -78,7 +78,7 @@ Devise.setup do |config| # `config.http_authenticatable = [:database]` will enable it only for # database authentication. The supported strategies are: :database # = Support basic authentication with authentication key + password - # config.http_authenticatable = false + config.http_authenticatable = true # If 401 status code should be returned for AJAX requests. True by # default. diff --git a/config/locales/en.yml b/config/locales/en.yml index 3475e70c..3e0ecc23 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -152,6 +152,9 @@ en: invitations: accept: 'Accept invitation' reject: 'No, thanks' + new: + title: 'Create site' + submit: 'Create site' footer: powered_by: 'is developed by' templates: diff --git a/config/locales/es.yml b/config/locales/es.yml index 77899aed..96086185 100644 --- a/config/locales/es.yml +++ b/config/locales/es.yml @@ -7,6 +7,8 @@ es: email: 'Correo electrónico' password: 'Contraseña' password_confirmation: 'Confirmación de contraseña' + site: + name: 'Nombre' errors: models: invitadx: @@ -155,6 +157,9 @@ es: invitations: accept: 'Aceptar la invitación' reject: 'No, gracias' + new: + title: 'Crear un sitio' + submit: 'Crear sitio' footer: powered_by: 'es desarrollada por' i18n: diff --git a/config/routes.rb b/config/routes.rb index 35bdd760..086fe8c5 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -11,9 +11,7 @@ Rails.application.routes.draw do # como un objeto válido resources :invitadxs, only: [:create] - resources :sites, only: %i[index show], - constraints: { site_id: %r{[^/]+}, id: %r{[^/]+} } do - + resources :sites, constraints: { site_id: %r{[^/]+}, id: %r{[^/]+} } do get 'public/:type/:basename', to: 'sites#send_public_file' # Gestionar usuaries diff --git a/doc/crear_sitios.md b/doc/crear_sitios.md index f953d88f..e7cc3edb 100644 --- a/doc/crear_sitios.md +++ b/doc/crear_sitios.md @@ -105,3 +105,11 @@ falta (algunas plantillas tienen requisitos extraños). Las plantillas se instalan como gemas en los sitios, de forma que podemos cambiarla desde las opciones del sitio luego. + +## Internamente + +Al crear un sitio, clonar el esqueleto en el lugar correcto. Al +eliminarlo, eliminar el directorio. + +Lo correcto sería preguntar a todes les usuaries si están de acuerdo en +borrar el sitio. Si una no está de acuerdo, el borrado se cancela. diff --git a/test/controllers/sites_controller_test.rb b/test/controllers/sites_controller_test.rb new file mode 100644 index 00000000..2c3c334c --- /dev/null +++ b/test/controllers/sites_controller_test.rb @@ -0,0 +1,45 @@ +# frozen_string_literal: true + +class SitesControllerTest < ActionDispatch::IntegrationTest + setup do + @rol = create :rol + @site = @rol.site + @usuarie = @rol.usuarie + + @authorization = { + Authorization: ActionController::HttpAuthentication::Basic + .encode_credentials(@usuarie.email, @usuarie.password) + } + end + + teardown do + @site.destroy + end + + test 'se pueden ver' do + get sites_url, headers: @authorization + + assert_match @site.name, response.body + end + + test 'se puede ver el formulario de creación' do + get new_site_url, headers: @authorization + + assert_match(/