mirror of
https://0xacab.org/sutty/sutty
synced 2024-11-26 09:06:21 +00:00
Merge branch 'issue-159' into panel.sutty.nl
This commit is contained in:
commit
a58e1578bc
9 changed files with 226 additions and 24 deletions
14
app/models/privacy_policy.rb
Normal file
14
app/models/privacy_policy.rb
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
# Políticas de privacidad
|
||||||
|
class PrivacyPolicy < ApplicationRecord
|
||||||
|
extend Mobility
|
||||||
|
|
||||||
|
translates :title, type: :string, locale_accessors: true
|
||||||
|
translates :description, type: :text, locale_accessors: true
|
||||||
|
translates :content, type: :text, locale_accessors: true
|
||||||
|
|
||||||
|
validates :title, presence: true, uniqueness: true
|
||||||
|
validates :description, presence: true
|
||||||
|
validates :content, presence: true
|
||||||
|
end
|
|
@ -31,7 +31,7 @@ class Site
|
||||||
|
|
||||||
# Escribe los cambios en el repositorio
|
# Escribe los cambios en el repositorio
|
||||||
def write
|
def write
|
||||||
return if persisted?
|
return true if persisted?
|
||||||
|
|
||||||
@saved = Site::Writer.new(site: site, file: path, content: content.to_yaml).save.tap do |result|
|
@saved = Site::Writer.new(site: site, file: path, content: content.to_yaml).save.tap do |result|
|
||||||
# Actualizar el hash para no escribir dos veces
|
# Actualizar el hash para no escribir dos veces
|
||||||
|
|
|
@ -12,6 +12,10 @@ PostService = Struct.new(:site, :usuarie, :post, :params, keyword_init: true) do
|
||||||
post.usuaries << usuarie
|
post.usuaries << usuarie
|
||||||
params[:post][:draft] = true if site.invitade? usuarie
|
params[:post][:draft] = true if site.invitade? usuarie
|
||||||
|
|
||||||
|
params.require(:post).permit(:slug).tap do |p|
|
||||||
|
post.slug.value = p[:slug] if p[:slug].present?
|
||||||
|
end
|
||||||
|
|
||||||
commit(action: :created, file: update_related_posts) if post.update(post_params)
|
commit(action: :created, file: update_related_posts) if post.update(post_params)
|
||||||
|
|
||||||
# Devolver el post aunque no se haya salvado para poder rescatar los
|
# Devolver el post aunque no se haya salvado para poder rescatar los
|
||||||
|
|
|
@ -23,7 +23,8 @@ SiteService = Struct.new(:site, :usuarie, :params, keyword_init: true) do
|
||||||
site.config.write &&
|
site.config.write &&
|
||||||
commit_config(action: :create) &&
|
commit_config(action: :create) &&
|
||||||
add_licencias &&
|
add_licencias &&
|
||||||
add_code_of_conduct
|
add_code_of_conduct &&
|
||||||
|
add_privacy_policy
|
||||||
end
|
end
|
||||||
|
|
||||||
site
|
site
|
||||||
|
@ -97,25 +98,27 @@ SiteService = Struct.new(:site, :usuarie, :params, keyword_init: true) do
|
||||||
end
|
end
|
||||||
|
|
||||||
# Crea la licencia del sitio para cada locale disponible en el sitio
|
# Crea la licencia del sitio para cada locale disponible en el sitio
|
||||||
|
#
|
||||||
|
# @return [Boolean]
|
||||||
def add_licencias
|
def add_licencias
|
||||||
return unless site.layout? :license
|
return true unless site.layout? :license
|
||||||
|
|
||||||
site.locales.each do |locale|
|
with_all_locales do |locale|
|
||||||
next unless I18n.available_locales.include? locale
|
|
||||||
|
|
||||||
Mobility.with_locale(locale) do
|
|
||||||
add_licencia lang: locale
|
add_licencia lang: locale
|
||||||
end
|
end.compact.map(&:valid?).all?
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Crea una licencia
|
||||||
|
#
|
||||||
|
# @return [Post]
|
||||||
def add_licencia(lang:)
|
def add_licencia(lang:)
|
||||||
params = ActionController::Parameters.new(
|
params = ActionController::Parameters.new(
|
||||||
post: {
|
post: {
|
||||||
layout: 'license',
|
layout: 'license',
|
||||||
|
slug: Jekyll::Utils.slugify(I18n.t('activerecord.models.licencia')),
|
||||||
lang: lang,
|
lang: lang,
|
||||||
title: site.licencia.name,
|
title: site.licencia.name,
|
||||||
description: I18n.t('sites.form.licencia.title'),
|
description: site.licencia.description,
|
||||||
content: CommonMarker.render_html(site.licencia.deed)
|
content: CommonMarker.render_html(site.licencia.deed)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -125,18 +128,22 @@ SiteService = Struct.new(:site, :usuarie, :params, keyword_init: true) do
|
||||||
|
|
||||||
# Encuentra la licencia a partir de su enlace permanente y le cambia
|
# Encuentra la licencia a partir de su enlace permanente y le cambia
|
||||||
# el contenido
|
# el contenido
|
||||||
|
#
|
||||||
|
# @return [Boolean]
|
||||||
def change_licencias
|
def change_licencias
|
||||||
site.locales.each do |locale|
|
return true unless site.layout? :license
|
||||||
next unless I18n.available_locales.include? locale
|
|
||||||
|
|
||||||
Mobility.with_locale(locale) do
|
with_all_locales do |locale|
|
||||||
post = site.posts(lang: locale).find_by(layout: 'license')
|
post = site.posts(lang: locale).find_by(layout: 'license')
|
||||||
|
|
||||||
change_licencia(post: post) if post
|
change_licencia(post: post) if post
|
||||||
end
|
end.compact.map(&:valid?).all?
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Cambia una licencia
|
||||||
|
#
|
||||||
|
# @param :post [Post]
|
||||||
|
# @return [Post]
|
||||||
def change_licencia(post:)
|
def change_licencia(post:)
|
||||||
params = ActionController::Parameters.new(
|
params = ActionController::Parameters.new(
|
||||||
post: {
|
post: {
|
||||||
|
@ -149,8 +156,11 @@ SiteService = Struct.new(:site, :usuarie, :params, keyword_init: true) do
|
||||||
params: params).update
|
params: params).update
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Agrega un código de conducta
|
||||||
|
#
|
||||||
|
# @return [Boolean]
|
||||||
def add_code_of_conduct
|
def add_code_of_conduct
|
||||||
return unless site.layout?(:code_of_conduct) || site.layout?(:page)
|
return true unless site.layout?(:code_of_conduct) || site.layout?(:page)
|
||||||
|
|
||||||
# TODO: soportar más códigos de conducta
|
# TODO: soportar más códigos de conducta
|
||||||
coc = CodeOfConduct.first
|
coc = CodeOfConduct.first
|
||||||
|
@ -161,13 +171,36 @@ SiteService = Struct.new(:site, :usuarie, :params, keyword_init: true) do
|
||||||
layout: site.layout?(:code_of_conduct) ? 'code_of_conduct' : 'page',
|
layout: site.layout?(:code_of_conduct) ? 'code_of_conduct' : 'page',
|
||||||
lang: locale.to_s,
|
lang: locale.to_s,
|
||||||
title: coc.title,
|
title: coc.title,
|
||||||
description: coc.description
|
description: coc.description,
|
||||||
content: CommonMarker.render_html(coc.content)
|
content: CommonMarker.render_html(coc.content)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
PostService.new(site: site, usuarie: usuarie, params: params).create
|
PostService.new(site: site, usuarie: usuarie, params: params).create
|
||||||
|
end.compact.map(&:valid?).all?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Agrega política de privacidad
|
||||||
|
#
|
||||||
|
# @return [Boolean]
|
||||||
|
def add_privacy_policy
|
||||||
|
return true unless site.layout?(:privacy_policy) || site.layout?(:page)
|
||||||
|
|
||||||
|
pp = PrivacyPolicy.first
|
||||||
|
|
||||||
|
with_all_locales do |locale|
|
||||||
|
params = ActionController::Parameters.new(
|
||||||
|
post: {
|
||||||
|
layout: site.layout?(:privacy_policy) ? 'privacy_policy' : 'page',
|
||||||
|
lang: locale.to_s,
|
||||||
|
title: pp.title,
|
||||||
|
description: pp.description,
|
||||||
|
content: CommonMarker.render_html(pp.content)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
PostService.new(site: site, usuarie: usuarie, params: params).create
|
||||||
|
end.compact.map(&:valid?).all?
|
||||||
end
|
end
|
||||||
|
|
||||||
# Crea los deploys necesarios para sincronizar a otros nodos de Sutty
|
# Crea los deploys necesarios para sincronizar a otros nodos de Sutty
|
||||||
|
@ -188,4 +221,16 @@ SiteService = Struct.new(:site, :usuarie, :params, keyword_init: true) do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def with_all_locales(&block)
|
||||||
|
site.locales.map do |locale|
|
||||||
|
next unless I18n.available_locales.include? locale
|
||||||
|
|
||||||
|
Mobility.with_locale(locale) do
|
||||||
|
yield locale
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -15,6 +15,8 @@ ActiveSupport::Inflector.inflections(:en) do |inflect|
|
||||||
inflect.singular 'rollups', 'rollup'
|
inflect.singular 'rollups', 'rollup'
|
||||||
inflect.plural 'code_of_conduct', 'codes_of_conduct'
|
inflect.plural 'code_of_conduct', 'codes_of_conduct'
|
||||||
inflect.singular 'codes_of_conduct', 'code_of_conduct'
|
inflect.singular 'codes_of_conduct', 'code_of_conduct'
|
||||||
|
inflect.plural 'privacy_policy', 'privacy_policies'
|
||||||
|
inflect.singular 'privacy_policies', 'privacy_policy'
|
||||||
end
|
end
|
||||||
|
|
||||||
ActiveSupport::Inflector.inflections(:es) do |inflect|
|
ActiveSupport::Inflector.inflections(:es) do |inflect|
|
||||||
|
@ -32,4 +34,6 @@ ActiveSupport::Inflector.inflections(:es) do |inflect|
|
||||||
inflect.singular 'rollups', 'rollup'
|
inflect.singular 'rollups', 'rollup'
|
||||||
inflect.plural 'code_of_conduct', 'codes_of_conduct'
|
inflect.plural 'code_of_conduct', 'codes_of_conduct'
|
||||||
inflect.singular 'codes_of_conduct', 'code_of_conduct'
|
inflect.singular 'codes_of_conduct', 'code_of_conduct'
|
||||||
|
inflect.plural 'privacy_policy', 'privacy_policies'
|
||||||
|
inflect.singular 'privacy_policies', 'privacy_policy'
|
||||||
end
|
end
|
||||||
|
|
|
@ -12,7 +12,7 @@ class AddCodeOfConduct < ActiveRecord::Migration[6.1]
|
||||||
|
|
||||||
# XXX: En lugar de ponerlo en las seeds
|
# XXX: En lugar de ponerlo en las seeds
|
||||||
YAML.safe_load(File.read('db/seeds/codes_of_conduct.yml')).each do |coc|
|
YAML.safe_load(File.read('db/seeds/codes_of_conduct.yml')).each do |coc|
|
||||||
CodigoDeConducta.new(**coc).save!
|
CodeOfConduct.new(**coc).save!
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
22
db/migrate/20230322231344_add_privacy_policy.rb
Normal file
22
db/migrate/20230322231344_add_privacy_policy.rb
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
# Agrega políticas de privacidad
|
||||||
|
class AddPrivacyPolicy < ActiveRecord::Migration[6.1]
|
||||||
|
def up
|
||||||
|
create_table :privacy_policies do |t|
|
||||||
|
t.timestamps
|
||||||
|
t.string :title
|
||||||
|
t.text :description
|
||||||
|
t.text :content
|
||||||
|
end
|
||||||
|
|
||||||
|
# XXX: En lugar de ponerlo en las seeds
|
||||||
|
YAML.safe_load(File.read('db/seeds/privacy_policies.yml')).each do |pp|
|
||||||
|
PrivacyPolicy.new(**pp).save!
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def down
|
||||||
|
drop_table :privacy_policies
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,6 +1,6 @@
|
||||||
---
|
---
|
||||||
- name_en: "Codes for sharing"
|
- title_en: "Codes for sharing"
|
||||||
name_es: "Códigos para compartir"
|
title_es: "Códigos para compartir"
|
||||||
description_en: "Codes of conduct allow inclusive communities."
|
description_en: "Codes of conduct allow inclusive communities."
|
||||||
description_es: "Los códigos de convivencia nos permiten alojar comunidades inclusivas."
|
description_es: "Los códigos de convivencia nos permiten alojar comunidades inclusivas."
|
||||||
content_en: |
|
content_en: |
|
||||||
|
|
113
db/seeds/privacy_policies.yml
Normal file
113
db/seeds/privacy_policies.yml
Normal file
|
@ -0,0 +1,113 @@
|
||||||
|
---
|
||||||
|
- title_en: "Privacy Policy"
|
||||||
|
title_es: "Políticas de privacidad"
|
||||||
|
description_en: "With what care does this site handles personal data of its users and visitors?"
|
||||||
|
description_es: "¿Cuáles son los cuidados de este sitio con respecto a sus usuaries y visitantes?"
|
||||||
|
content_en: |
|
||||||
|
> We use "them" as neutral pronoun to refer to people regardless of
|
||||||
|
> gender identity.
|
||||||
|
|
||||||
|
This document details Sutty's privacy policy, including web site,
|
||||||
|
platform, other infrastructure (support channels, etc.) and web sites
|
||||||
|
generated by users.
|
||||||
|
|
||||||
|
## This is too long!
|
||||||
|
|
||||||
|
* Sutty doesn't collect any kind of personal data.
|
||||||
|
|
||||||
|
* Sutty may only collect statistical data that doesn't identify
|
||||||
|
individuals.
|
||||||
|
|
||||||
|
## Analytic data
|
||||||
|
|
||||||
|
Sutty may only collect data for analytics (number of visits, duration,
|
||||||
|
etc.), not associated to personal data.
|
||||||
|
|
||||||
|
Analytical data collected for every web site can only be used internally
|
||||||
|
by Sutty. Sutty doesn't share any data privately with any third
|
||||||
|
parties. Selected analytical data could be used publicly.
|
||||||
|
|
||||||
|
Sutty doesn't recommend personal data collection in any way, but it
|
||||||
|
doesn't monitor if its users use third party services with their own
|
||||||
|
privacy policies. We recommend users and visitors to inform themselves
|
||||||
|
before using third parties analytics services.
|
||||||
|
|
||||||
|
## No personal data collection
|
||||||
|
|
||||||
|
Sutty doesn't collect IP addresses from users nor visitors in any way.
|
||||||
|
|
||||||
|
Sutty doesn't ask for personal data for registering user accounts in its
|
||||||
|
platform.
|
||||||
|
|
||||||
|
Sutty only uses session "cookies" to identify users during their use of
|
||||||
|
the platform. It doesn't use "cookies" to identify visitors of web
|
||||||
|
sites hosted by Sutty.
|
||||||
|
|
||||||
|
The only exception where Sutty could collect personal data is during
|
||||||
|
service payment. Digital safety measures will be taken to keep this
|
||||||
|
information and to discard it if possible after needed.
|
||||||
|
|
||||||
|
Users will be notified when their personal data is removed.
|
||||||
|
|
||||||
|
If users decide to host their web sites with third parties, they must
|
||||||
|
inform themselves about the corresponding privacy policies. Sutty only
|
||||||
|
recommends third parties with privacy policies compatible with these.
|
||||||
|
content_es: |
|
||||||
|
> Utilizamos la e como pronombre neutro para referirnos a personas
|
||||||
|
> independientemente de su identidad de género, por ejemplo “usuarie”.
|
||||||
|
|
||||||
|
Este documento detalla la política de privacidad de Sutty, incluyendo
|
||||||
|
sitio web, plataforma de edición, infraestructura relacionada (salas de
|
||||||
|
chat, etc.) y sitios creados por sus usuaries a través de la plataforma,
|
||||||
|
en adelante "Sutty".
|
||||||
|
|
||||||
|
## ¡Esto es demasiado largo!
|
||||||
|
|
||||||
|
Un resumen:
|
||||||
|
|
||||||
|
* Sutty no recolecta datos personales de ningún tipo
|
||||||
|
|
||||||
|
* Sutty solo recolectaría datos analíticos que no identifican a
|
||||||
|
personas
|
||||||
|
|
||||||
|
## Datos analíticos
|
||||||
|
|
||||||
|
La única recolección de datos realizada por Sutty es con fines
|
||||||
|
analíticos (cantidad de visitas, duración, etc.), no asociados a datos
|
||||||
|
personales.
|
||||||
|
|
||||||
|
Los datos analíticos recolectados por cada sitio podrán ser utilizados
|
||||||
|
internamente por Sutty. Sutty no comparte datos analíticos con
|
||||||
|
terceros en forma privada. Datos analíticos seleccionados podrán ser
|
||||||
|
utilizados públicamente.
|
||||||
|
|
||||||
|
Sutty no recomienda la recolección de datos personales de ninguna forma,
|
||||||
|
pero no monitorea que les usuaries utilicen servicios de terceros con
|
||||||
|
sus propias políticas de privacidad. Recomendamos a les usuaries y
|
||||||
|
visitantes informarse antes de utilizar servicios de estadísticas de
|
||||||
|
terceros.
|
||||||
|
|
||||||
|
## No registro de datos personales
|
||||||
|
|
||||||
|
Sutty no registra direcciones IP de usuaries ni de visitantes de ninguna
|
||||||
|
forma.
|
||||||
|
|
||||||
|
Sutty no solicita datos personales para el registro de cuentas de
|
||||||
|
usuarie en su plataforma.
|
||||||
|
|
||||||
|
Sutty solo utiliza “cookies” de sesión para identificar usuaries
|
||||||
|
mientras utilicen la plataforma. No se utilizan “cookies” para
|
||||||
|
identificar visitantes a los sitios alojados por Sutty.
|
||||||
|
|
||||||
|
El único caso en el que Sutty podría solicitar datos personales es
|
||||||
|
durante el pago de servicios. Se tomarán medidas de seguridad digital
|
||||||
|
para salvaguardar esta información y descartar lo que sea posible una
|
||||||
|
vez que ya no sea necesaria.
|
||||||
|
|
||||||
|
Se notificará a les usuaries cuando su información personal sea
|
||||||
|
eliminada.
|
||||||
|
|
||||||
|
Si les usuaries deciden alojar sus sitios con terceros, deberán
|
||||||
|
informarse de las políticas de privacidad correspondientes. Sutty
|
||||||
|
recomienda servicios de terceros con políticas de privacidad coherentes
|
||||||
|
con estas.
|
Loading…
Reference in a new issue