Filter languages with opt out (#3175)

* Remove allowed_languages and add filtered_languages

* Use filtered_languages instead of allowed_languages
This commit is contained in:
Matt Jankowski 2017-05-20 11:32:44 -04:00 committed by Eugen Rochko
parent 2e112e2406
commit 8f4b7c1820
21 changed files with 30 additions and 41 deletions

View file

@ -26,7 +26,7 @@ class Settings::PreferencesController < ApplicationController
def user_params def user_params
params.require(:user).permit( params.require(:user).permit(
:locale, :locale,
allowed_languages: [] filtered_languages: []
) )
end end

View file

@ -352,7 +352,7 @@ code {
} }
} }
.user_allowed_languages { .user_filtered_languages {
li { li {
float: left; float: left;
width: 50%; width: 50%;

View file

@ -99,7 +99,7 @@ class Account < ApplicationRecord
prefix: true, prefix: true,
allow_nil: true allow_nil: true
delegate :allowed_languages, to: :user, prefix: false, allow_nil: true delegate :filtered_languages, to: :user, prefix: false, allow_nil: true
def local? def local?
domain.nil? domain.nil?

View file

@ -142,8 +142,8 @@ class Status < ApplicationRecord
before_validation :set_conversation before_validation :set_conversation
class << self class << self
def in_allowed_languages(account) def not_in_filtered_languages(account)
where(language: account.allowed_languages) where.not(language: account.filtered_languages)
end end
def as_home_timeline(account) def as_home_timeline(account)
@ -234,7 +234,7 @@ class Status < ApplicationRecord
def filter_timeline_for_account(query, account, local_only) def filter_timeline_for_account(query, account, local_only)
query = query.not_excluded_by_account(account) query = query.not_excluded_by_account(account)
query = query.not_domain_blocked_by_account(account) unless local_only query = query.not_domain_blocked_by_account(account) unless local_only
query = query.in_allowed_languages(account) if account.allowed_languages.present? query = query.not_in_filtered_languages(account) if account.filtered_languages.present?
query.merge(account_silencing_filter(account)) query.merge(account_silencing_filter(account))
end end

View file

@ -30,7 +30,7 @@
# otp_required_for_login :boolean # otp_required_for_login :boolean
# last_emailed_at :datetime # last_emailed_at :datetime
# otp_backup_codes :string is an Array # otp_backup_codes :string is an Array
# allowed_languages :string default([]), not null, is an Array # filtered_languages :string default([]), not null, is an Array
# #
class User < ApplicationRecord class User < ApplicationRecord
@ -83,6 +83,6 @@ class User < ApplicationRecord
private private
def sanitize_languages def sanitize_languages
allowed_languages.reject!(&:blank?) filtered_languages.reject!(&:blank?)
end end
end end

View file

@ -12,7 +12,7 @@
label_method: lambda { |locale| human_locale(locale) }, label_method: lambda { |locale| human_locale(locale) },
selected: I18n.locale selected: I18n.locale
= f.input :allowed_languages, = f.input :filtered_languages,
collection: I18n.available_locales, collection: I18n.available_locales,
wrapper: :with_label, wrapper: :with_label,
include_blank: false, include_blank: false,

View file

@ -12,8 +12,6 @@ ar:
data: ملف CSV تم تصديره من خادوم مثيل آخر لماستدون data: ملف CSV تم تصديره من خادوم مثيل آخر لماستدون
sessions: sessions:
otp: أدخل الرمز الثنائي من هاتفك أو استخدم أحد رموز الاسترداد. otp: أدخل الرمز الثنائي من هاتفك أو استخدم أحد رموز الاسترداد.
user:
allowed_languages: سوف يتم السماح بعرض اللغات المختارة على خيوطك المتسلسلة العامة أما التي لم يتم تحديدها فسوف تصفّى.
labels: labels:
defaults: defaults:
avatar: الصورة الرمزية avatar: الصورة الرمزية

View file

@ -17,7 +17,7 @@ en:
sessions: sessions:
otp: Enter the Two-factor code from your phone or use one of your recovery codes. otp: Enter the Two-factor code from your phone or use one of your recovery codes.
user: user:
allowed_languages: These languages will be allowed in your public timelines. Languages that are not selected will be filtered out. filtered_languages: Selected languages will be removed from your public timelines.
labels: labels:
defaults: defaults:
avatar: Avatar avatar: Avatar

View file

@ -12,8 +12,6 @@ fa:
data: پروندهٔ CSV که از سرور ماستدون دیگری برون‌سپاری شده data: پروندهٔ CSV که از سرور ماستدون دیگری برون‌سپاری شده
sessions: sessions:
otp: کد تأیید دومرحله‌ای را از تلفن خود وارد کنید یا یکی از کدهای بازیابی را به کار ببرید. otp: کد تأیید دومرحله‌ای را از تلفن خود وارد کنید یا یکی از کدهای بازیابی را به کار ببرید.
user:
allowed_languages: این زبان‌ها در فهرست عمومی نوشته‌ها مجاز خواهند بود. زبان‌هایی که انتخاب نشده باشند به این فهرست راه پیدا نمی‌کنند.
labels: labels:
defaults: defaults:
avatar: تصویر نمایه avatar: تصویر نمایه

View file

@ -16,8 +16,6 @@ he:
data: 'קובץ CSV שיוצא משרת מסטודון אחר' data: 'קובץ CSV שיוצא משרת מסטודון אחר'
sessions: sessions:
otp: 'נא להקליד קוד אימות דו-שלבי ממכשירך או קוד אחזור גישה.' otp: 'נא להקליד קוד אימות דו-שלבי ממכשירך או קוד אחזור גישה.'
user:
allowed_languages: אלו השפות שיהיה מותרות בצירי הזמן הציבוריים שלך. שפות שלא ייבחרו יפולטרו מעיני הקוראים.
labels: labels:
defaults: defaults:
avatar: תמונת פרופיל avatar: תמונת פרופיל

View file

@ -12,11 +12,8 @@ ja:
data: 他の Mastodon インスタンスからエクスポートしたCSVファイルを選択して下さい data: 他の Mastodon インスタンスからエクスポートしたCSVファイルを選択して下さい
sessions: sessions:
otp: 携帯電話に表示された2段階認証コードを入力するか、生成したリカバリーコードを使用してください。 otp: 携帯電話に表示された2段階認証コードを入力するか、生成したリカバリーコードを使用してください。
user:
allowed_languages: 選択した言語があなたの公開タイムラインに表示されます。選択していない言語は取り除かれます。
labels: labels:
defaults: defaults:
allowed_languages: 許可する言語
avatar: アイコン avatar: アイコン
confirm_new_password: 新しいパスワード(確認用) confirm_new_password: 新しいパスワード(確認用)
confirm_password: パスワード(確認用) confirm_password: パスワード(確認用)

View file

@ -12,11 +12,8 @@ oc:
data: Fichièr CSV exportat duna autra instància Mastodon data: Fichièr CSV exportat duna autra instància Mastodon
sessions: sessions:
otp: Picatz lo còdi dautentificacion en dos temps (Two factor code) de vòstre mobil o utilizatz un de vòstres còdis de recuperacion. otp: Picatz lo còdi dautentificacion en dos temps (Two factor code) de vòstre mobil o utilizatz un de vòstres còdis de recuperacion.
user:
allowed_languages: Aquestas lengas seràn las que seràn autorizadas dins vòstre flux public. Las lengas pas causidas seràn rescondudas.
labels: labels:
defaults: defaults:
allowed_languages: Lengas autorizadas
avatar: Avatar avatar: Avatar
confirm_new_password: Confirmacion del nòu senhal confirm_new_password: Confirmacion del nòu senhal
confirm_password: Confirmatz lo nòu senhal confirm_password: Confirmatz lo nòu senhal

View file

@ -12,8 +12,6 @@ pl:
data: Plik CSV wyeksportowany z innej instancji Mastodona data: Plik CSV wyeksportowany z innej instancji Mastodona
sessions: sessions:
otp: Wprowadź kod weryfikacji dwuetapowej z telefonu lub wykorzystaj jeden z kodów zapasowych. otp: Wprowadź kod weryfikacji dwuetapowej z telefonu lub wykorzystaj jeden z kodów zapasowych.
user:
allowed_languages: Te języki będą wyświetlać się na Twojej osi czasu. Wpisy w niezaznaczonych językach nie będą widoczne.
labels: labels:
defaults: defaults:
avatar: Awatar avatar: Awatar

View file

@ -12,8 +12,6 @@ pt-BR:
data: Arquivo CSV exportado de outra instancia Mastodon data: Arquivo CSV exportado de outra instancia Mastodon
sessions: sessions:
otp: Entre com o código de 2 passos do seu telefone ou use os códiogos de recuperação. otp: Entre com o código de 2 passos do seu telefone ou use os códiogos de recuperação.
user:
allowed_languages: Essas línguas vão ser permitidas na sua timeline pública. Línguas que não forem selecionadas serão filtradas.
labels: labels:
defaults: defaults:
avatar: Avatar avatar: Avatar

View file

@ -9,15 +9,13 @@ th:
other: '%{count} characters left' other: '%{count} characters left'
header: PNG, GIF or JPG. At most 2MB. Will be downscaled to 700x335px header: PNG, GIF or JPG. At most 2MB. Will be downscaled to 700x335px
locked: Requires you to manually approve followers and defaults post privacy to followers-only locked: Requires you to manually approve followers and defaults post privacy to followers-only
note: note:
one: '1 character left' one: '1 character left'
other: '%{count} characters left' other: '%{count} characters left'
imports: imports:
data: CSV file exported from another Mastodon instance data: CSV file exported from another Mastodon instance
sessions: sessions:
otp: Enter the Two-factor code from your phone or use one of your recovery codes. otp: Enter the Two-factor code from your phone or use one of your recovery codes.
user:
allowed_languages: These languages will be allowed in your public timelines. Languages that are not selected will be filtered out.
labels: labels:
defaults: defaults:
avatar: Avatar avatar: Avatar

View file

@ -12,8 +12,6 @@ zh-CN:
data: 自其他服务站导出的 CSV 文件 data: 自其他服务站导出的 CSV 文件
sessions: sessions:
otp: 输入你手机生成的两步验证码,或者恢复代码。 otp: 输入你手机生成的两步验证码,或者恢复代码。
user:
allowed_languages: 允许下列语言的内容出现在你的公共时间线上。
labels: labels:
defaults: defaults:
avatar: 头像 avatar: 头像

View file

@ -0,0 +1,9 @@
class ChangeLanguageFilterToOptOut < ActiveRecord::Migration[5.0]
def change
remove_index :users, :allowed_languages
remove_column :users, :allowed_languages
add_column :users, :filtered_languages, :string, array: true, default: [], null: false
add_index :users, :filtered_languages, using: :gin
end
end

View file

@ -10,7 +10,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: 20170517205741) do ActiveRecord::Schema.define(version: 20170520145338) do
# These are extensions that must be enabled in order to support this database # These are extensions that must be enabled in order to support this database
enable_extension "plpgsql" enable_extension "plpgsql"
@ -350,11 +350,11 @@ ActiveRecord::Schema.define(version: 20170517205741) do
t.boolean "otp_required_for_login" t.boolean "otp_required_for_login"
t.datetime "last_emailed_at" t.datetime "last_emailed_at"
t.string "otp_backup_codes", array: true t.string "otp_backup_codes", array: true
t.string "allowed_languages", default: [], null: false, array: true t.string "filtered_languages", default: [], null: false, array: true
t.index ["account_id"], name: "index_users_on_account_id", using: :btree t.index ["account_id"], name: "index_users_on_account_id", using: :btree
t.index ["allowed_languages"], name: "index_users_on_allowed_languages", using: :gin
t.index ["confirmation_token"], name: "index_users_on_confirmation_token", unique: true, using: :btree t.index ["confirmation_token"], name: "index_users_on_confirmation_token", unique: true, using: :btree
t.index ["email"], name: "index_users_on_email", unique: true, using: :btree t.index ["email"], name: "index_users_on_email", unique: true, using: :btree
t.index ["filtered_languages"], name: "index_users_on_filtered_languages", using: :gin
t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true, using: :btree t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true, using: :btree
end end

View file

@ -3,7 +3,7 @@ require 'rails_helper'
describe Settings::PreferencesController do describe Settings::PreferencesController do
render_views render_views
let(:user) { Fabricate(:user, allowed_languages: []) } let(:user) { Fabricate(:user, filtered_languages: []) }
before do before do
sign_in user, scope: :user sign_in user, scope: :user
@ -18,12 +18,12 @@ describe Settings::PreferencesController do
describe 'PUT #update' do describe 'PUT #update' do
it 'updates the user record' do it 'updates the user record' do
put :update, params: { user: { locale: 'en', allowed_languages: ['es', 'fr', ''] } } put :update, params: { user: { locale: 'en', filtered_languages: ['es', 'fr', ''] } }
expect(response).to redirect_to(settings_preferences_path) expect(response).to redirect_to(settings_preferences_path)
user.reload user.reload
expect(user.locale).to eq 'en' expect(user.locale).to eq 'en'
expect(user.allowed_languages).to eq ['es', 'fr'] expect(user.filtered_languages).to eq ['es', 'fr']
end end
it 'updates user settings' do it 'updates user settings' do

View file

@ -512,7 +512,7 @@ RSpec.describe Status, type: :model do
context 'with language preferences' do context 'with language preferences' do
it 'excludes statuses in languages not allowed by the account user' do it 'excludes statuses in languages not allowed by the account user' do
user = Fabricate(:user, allowed_languages: [:en, :es]) user = Fabricate(:user, filtered_languages: [:fr])
@account.update(user: user) @account.update(user: user)
en_status = Fabricate(:status, language: 'en') en_status = Fabricate(:status, language: 'en')
es_status = Fabricate(:status, language: 'es') es_status = Fabricate(:status, language: 'es')
@ -525,7 +525,7 @@ RSpec.describe Status, type: :model do
end end
it 'includes all languages when user does not have a setting' do it 'includes all languages when user does not have a setting' do
user = Fabricate(:user, allowed_languages: []) user = Fabricate(:user, filtered_languages: [])
@account.update(user: user) @account.update(user: user)
en_status = Fabricate(:status, language: 'en') en_status = Fabricate(:status, language: 'en')

View file

@ -24,9 +24,9 @@ RSpec.describe User, type: :model do
end end
it 'cleans out empty string from languages' do it 'cleans out empty string from languages' do
user = Fabricate.build(:user, allowed_languages: ['']) user = Fabricate.build(:user, filtered_languages: [''])
user.valid? user.valid?
expect(user.allowed_languages).to eq [] expect(user.filtered_languages).to eq []
end end
end end