Merge branch 'master' into skylight
This commit is contained in:
commit
945e5bf9cc
|
@ -22,6 +22,8 @@ OTP_SECRET=
|
||||||
# SINGLE_USER_MODE=true
|
# SINGLE_USER_MODE=true
|
||||||
# Prevent registrations with following e-mail domains
|
# Prevent registrations with following e-mail domains
|
||||||
# EMAIL_DOMAIN_BLACKLIST=example1.com|example2.de|etc
|
# EMAIL_DOMAIN_BLACKLIST=example1.com|example2.de|etc
|
||||||
|
# Only allow registrations with the following e-mail domains
|
||||||
|
# EMAIL_DOMAIN_WHITELIST=example1.com|example2.de|etc
|
||||||
|
|
||||||
# E-mail configuration
|
# E-mail configuration
|
||||||
SMTP_SERVER=smtp.mailgun.org
|
SMTP_SERVER=smtp.mailgun.org
|
||||||
|
|
5
Gemfile
5
Gemfile
|
@ -8,8 +8,6 @@ gem 'sass-rails', '~> 5.0'
|
||||||
gem 'uglifier', '>= 1.3.0'
|
gem 'uglifier', '>= 1.3.0'
|
||||||
gem 'coffee-rails', '~> 4.1.0'
|
gem 'coffee-rails', '~> 4.1.0'
|
||||||
gem 'jquery-rails'
|
gem 'jquery-rails'
|
||||||
gem 'jbuilder', '~> 2.0'
|
|
||||||
gem 'sdoc', '~> 0.4.0', group: :doc
|
|
||||||
gem 'puma'
|
gem 'puma'
|
||||||
|
|
||||||
gem 'hamlit-rails'
|
gem 'hamlit-rails'
|
||||||
|
@ -70,9 +68,10 @@ group :development, :test do
|
||||||
end
|
end
|
||||||
|
|
||||||
group :test do
|
group :test do
|
||||||
|
gem 'faker'
|
||||||
|
gem 'rspec-sidekiq'
|
||||||
gem 'simplecov', require: false
|
gem 'simplecov', require: false
|
||||||
gem 'webmock'
|
gem 'webmock'
|
||||||
gem 'rspec-sidekiq'
|
|
||||||
end
|
end
|
||||||
|
|
||||||
group :development do
|
group :development do
|
||||||
|
|
14
Gemfile.lock
14
Gemfile.lock
|
@ -149,6 +149,8 @@ GEM
|
||||||
erubis (2.7.0)
|
erubis (2.7.0)
|
||||||
execjs (2.7.0)
|
execjs (2.7.0)
|
||||||
fabrication (2.15.2)
|
fabrication (2.15.2)
|
||||||
|
faker (1.6.6)
|
||||||
|
i18n (~> 0.5)
|
||||||
fast_blank (1.0.0)
|
fast_blank (1.0.0)
|
||||||
font-awesome-rails (4.6.3.1)
|
font-awesome-rails (4.6.3.1)
|
||||||
railties (>= 3.2, < 5.1)
|
railties (>= 3.2, < 5.1)
|
||||||
|
@ -196,9 +198,6 @@ GEM
|
||||||
parser (>= 2.2.3.0)
|
parser (>= 2.2.3.0)
|
||||||
term-ansicolor (>= 1.3.2)
|
term-ansicolor (>= 1.3.2)
|
||||||
terminal-table (>= 1.5.1)
|
terminal-table (>= 1.5.1)
|
||||||
jbuilder (2.6.0)
|
|
||||||
activesupport (>= 3.0.0, < 5.1)
|
|
||||||
multi_json (~> 1.2)
|
|
||||||
jmespath (1.3.1)
|
jmespath (1.3.1)
|
||||||
jquery-rails (4.1.1)
|
jquery-rails (4.1.1)
|
||||||
rails-dom-testing (>= 1, < 3)
|
rails-dom-testing (>= 1, < 3)
|
||||||
|
@ -229,7 +228,6 @@ GEM
|
||||||
mimemagic (0.3.2)
|
mimemagic (0.3.2)
|
||||||
mini_portile2 (2.1.0)
|
mini_portile2 (2.1.0)
|
||||||
minitest (5.10.1)
|
minitest (5.10.1)
|
||||||
multi_json (1.12.1)
|
|
||||||
net-scp (1.2.1)
|
net-scp (1.2.1)
|
||||||
net-ssh (>= 2.6.5)
|
net-ssh (>= 2.6.5)
|
||||||
net-ssh (4.0.1)
|
net-ssh (4.0.1)
|
||||||
|
@ -308,8 +306,6 @@ GEM
|
||||||
thor (>= 0.18.1, < 2.0)
|
thor (>= 0.18.1, < 2.0)
|
||||||
rainbow (2.1.0)
|
rainbow (2.1.0)
|
||||||
rake (12.0.0)
|
rake (12.0.0)
|
||||||
rdoc (4.2.2)
|
|
||||||
json (~> 1.4)
|
|
||||||
react-rails (1.10.0)
|
react-rails (1.10.0)
|
||||||
babel-transpiler (>= 0.7.0)
|
babel-transpiler (>= 0.7.0)
|
||||||
coffee-script-source (~> 1.8)
|
coffee-script-source (~> 1.8)
|
||||||
|
@ -379,9 +375,6 @@ GEM
|
||||||
sprockets (>= 2.8, < 4.0)
|
sprockets (>= 2.8, < 4.0)
|
||||||
sprockets-rails (>= 2.0, < 4.0)
|
sprockets-rails (>= 2.0, < 4.0)
|
||||||
tilt (>= 1.1, < 3)
|
tilt (>= 1.1, < 3)
|
||||||
sdoc (0.4.1)
|
|
||||||
json (~> 1.7, >= 1.7.7)
|
|
||||||
rdoc (~> 4.0)
|
|
||||||
sidekiq (4.2.7)
|
sidekiq (4.2.7)
|
||||||
concurrent-ruby (~> 1.0)
|
concurrent-ruby (~> 1.0)
|
||||||
connection_pool (~> 2.2, >= 2.2.0)
|
connection_pool (~> 2.2, >= 2.2.0)
|
||||||
|
@ -475,6 +468,7 @@ DEPENDENCIES
|
||||||
doorkeeper
|
doorkeeper
|
||||||
dotenv-rails
|
dotenv-rails
|
||||||
fabrication
|
fabrication
|
||||||
|
faker
|
||||||
fast_blank
|
fast_blank
|
||||||
font-awesome-rails
|
font-awesome-rails
|
||||||
fuubar
|
fuubar
|
||||||
|
@ -485,7 +479,6 @@ DEPENDENCIES
|
||||||
http
|
http
|
||||||
httplog
|
httplog
|
||||||
i18n-tasks (~> 0.9.6)
|
i18n-tasks (~> 0.9.6)
|
||||||
jbuilder (~> 2.0)
|
|
||||||
jquery-rails
|
jquery-rails
|
||||||
letter_opener
|
letter_opener
|
||||||
letter_opener_web
|
letter_opener_web
|
||||||
|
@ -516,7 +509,6 @@ DEPENDENCIES
|
||||||
rubocop
|
rubocop
|
||||||
ruby-oembed
|
ruby-oembed
|
||||||
sass-rails (~> 5.0)
|
sass-rails (~> 5.0)
|
||||||
sdoc (~> 0.4.0)
|
|
||||||
sidekiq
|
sidekiq
|
||||||
sidekiq-skylight
|
sidekiq-skylight
|
||||||
sidekiq-unique-jobs
|
sidekiq-unique-jobs
|
||||||
|
|
|
@ -5,9 +5,9 @@ const fi = {
|
||||||
"status.mention": "Mainitse @{name}",
|
"status.mention": "Mainitse @{name}",
|
||||||
"status.delete": "Poista",
|
"status.delete": "Poista",
|
||||||
"status.reply": "Vastaa",
|
"status.reply": "Vastaa",
|
||||||
"status.reblog": "Boostaa",
|
"status.reblog": "Buustaa",
|
||||||
"status.favourite": "Tykkää",
|
"status.favourite": "Tykkää",
|
||||||
"status.reblogged_by": "{name} boostattu",
|
"status.reblogged_by": "{name} buustasi",
|
||||||
"status.sensitive_warning": "Arkaluontoista sisältöä",
|
"status.sensitive_warning": "Arkaluontoista sisältöä",
|
||||||
"status.sensitive_toggle": "Klikkaa nähdäksesi",
|
"status.sensitive_toggle": "Klikkaa nähdäksesi",
|
||||||
"video_player.toggle_sound": "Äänet päälle/pois",
|
"video_player.toggle_sound": "Äänet päälle/pois",
|
||||||
|
@ -22,13 +22,13 @@ const fi = {
|
||||||
"account.followers": "Seuraajia",
|
"account.followers": "Seuraajia",
|
||||||
"account.follows_you": "Seuraa sinua",
|
"account.follows_you": "Seuraa sinua",
|
||||||
"account.requested": "Odottaa hyväksyntää",
|
"account.requested": "Odottaa hyväksyntää",
|
||||||
"getting_started.heading": "Päästä alkuun",
|
"getting_started.heading": "Aloitus",
|
||||||
"getting_started.about_addressing": "Voit seurata ihmisiä jos tiedät heidän käyttäjänimensä ja domainin missä he ovat syöttämällä e-mail-esque osoitteen Etsi kenttään.",
|
"getting_started.about_addressing": "Voit seurata ihmisiä jos tiedät heidän käyttäjänimensä ja domainin missä he ovat syöttämällä e-mail-esque osoitteen Etsi kenttään.",
|
||||||
"getting_started.about_shortcuts": "Jos etsimäsi henkilö on samassa domainissa kuin sinä, pelkkä käyttäjänimi kelpaa. Sama pätee kun mainitset ihmisiä statuksessasi",
|
"getting_started.about_shortcuts": "Jos etsimäsi henkilö on samassa domainissa kuin sinä, pelkkä käyttäjänimi kelpaa. Sama pätee kun mainitset ihmisiä statuksessasi",
|
||||||
"getting_started.open_source_notice": "Mastodon Mastodon on avoimen lähdekoodin ohjelma. Voit avustaa tai raportoida ongelmia githubissa {github}. {apps}.",
|
"getting_started.open_source_notice": "Mastodon Mastodon on avoimen lähdekoodin ohjelma. Voit avustaa tai raportoida ongelmia GitHub palvelussa {github}. {apps}.",
|
||||||
"column.home": "Koti",
|
"column.home": "Koti",
|
||||||
"column.community": "Paikallinen aikajana",
|
"column.community": "Paikallinen aikajana",
|
||||||
"column.public": "Yhdistetty aikajana",
|
"column.public": "Yleinen aikajana",
|
||||||
"column.notifications": "Ilmoitukset",
|
"column.notifications": "Ilmoitukset",
|
||||||
"tabs_bar.compose": "Luo",
|
"tabs_bar.compose": "Luo",
|
||||||
"tabs_bar.home": "Koti",
|
"tabs_bar.home": "Koti",
|
||||||
|
@ -41,7 +41,7 @@ const fi = {
|
||||||
"compose_form.spoiler": "Piiloita teksti varoituksen taakse",
|
"compose_form.spoiler": "Piiloita teksti varoituksen taakse",
|
||||||
"compose_form.private": "Merkitse yksityiseksi",
|
"compose_form.private": "Merkitse yksityiseksi",
|
||||||
"compose_form.privacy_disclaimer": "Sinun yksityinen status toimitetaan mainitsemallesi käyttäjille domaineissa {domains}. Luotatko {domainsCount, plural, one {tähän palvelimeen} other {näihin palvelimiin}}? Postauksen yksityisyys toimii van Mastodon palvelimilla. Jos {domains} {domainsCount, plural, one {ei ole Mastodon palvelin} other {eivät ole Mastodon palvelin}}, viestiin ei tule Yksityinen-merkintää, ja sitä voidaan boostata tai muuten tehdä näkyväksi muille vastaanottajille.",
|
"compose_form.privacy_disclaimer": "Sinun yksityinen status toimitetaan mainitsemallesi käyttäjille domaineissa {domains}. Luotatko {domainsCount, plural, one {tähän palvelimeen} other {näihin palvelimiin}}? Postauksen yksityisyys toimii van Mastodon palvelimilla. Jos {domains} {domainsCount, plural, one {ei ole Mastodon palvelin} other {eivät ole Mastodon palvelin}}, viestiin ei tule Yksityinen-merkintää, ja sitä voidaan boostata tai muuten tehdä näkyväksi muille vastaanottajille.",
|
||||||
"compose_form.unlisted": "Älä näytä julkisilla aikajanoilla",
|
"compose_form.unlisted": "Älä näytä yleisillä aikajanoilla",
|
||||||
"navigation_bar.edit_profile": "Muokkaa profiilia",
|
"navigation_bar.edit_profile": "Muokkaa profiilia",
|
||||||
"navigation_bar.preferences": "Ominaisuudet",
|
"navigation_bar.preferences": "Ominaisuudet",
|
||||||
"navigation_bar.community_timeline": "Paikallinen aikajana",
|
"navigation_bar.community_timeline": "Paikallinen aikajana",
|
||||||
|
@ -55,14 +55,14 @@ const fi = {
|
||||||
"upload_form.undo": "Peru",
|
"upload_form.undo": "Peru",
|
||||||
"notification.follow": "{name} seurasi sinua",
|
"notification.follow": "{name} seurasi sinua",
|
||||||
"notification.favourite": "{name} tykkäsi statuksestasi",
|
"notification.favourite": "{name} tykkäsi statuksestasi",
|
||||||
"notification.reblog": "{name} boostasi statustasi",
|
"notification.reblog": "{name} buustasi statustasi",
|
||||||
"notification.mention": "{name} mainitsi sinut",
|
"notification.mention": "{name} mainitsi sinut",
|
||||||
"notifications.column_settings.alert": "Työpöytä ilmoitukset",
|
"notifications.column_settings.alert": "Työpöytä ilmoitukset",
|
||||||
"notifications.column_settings.show": "Näytä sarakkeessa",
|
"notifications.column_settings.show": "Näytä sarakkeessa",
|
||||||
"notifications.column_settings.follow": "Uusia seuraajia:",
|
"notifications.column_settings.follow": "Uusia seuraajia:",
|
||||||
"notifications.column_settings.favourite": "Tykkäyksiä:",
|
"notifications.column_settings.favourite": "Tykkäyksiä:",
|
||||||
"notifications.column_settings.mention": "Mainintoja:",
|
"notifications.column_settings.mention": "Mainintoja:",
|
||||||
"notifications.column_settings.reblog": "Boosteja:",
|
"notifications.column_settings.reblog": "Buusteja:",
|
||||||
};
|
};
|
||||||
|
|
||||||
export default fi;
|
export default fi;
|
||||||
|
|
|
@ -34,6 +34,7 @@
|
||||||
text-align: center;
|
text-align: center;
|
||||||
position: relative;
|
position: relative;
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
|
text-shadow: 0 0 2px $color8;
|
||||||
|
|
||||||
small {
|
small {
|
||||||
display: block;
|
display: block;
|
||||||
|
@ -128,6 +129,7 @@
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
display: block;
|
display: block;
|
||||||
margin-bottom: 5px;
|
margin-bottom: 5px;
|
||||||
|
text-shadow: 0 0 2px $color8;
|
||||||
}
|
}
|
||||||
|
|
||||||
.counter-number {
|
.counter-number {
|
||||||
|
@ -385,5 +387,6 @@
|
||||||
.account__header__content {
|
.account__header__content {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
color: $color1;
|
color: $color1;
|
||||||
|
text-shadow: 0 0 2px $color8;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@ class RemoteFollowController < ApplicationController
|
||||||
|
|
||||||
def new
|
def new
|
||||||
@remote_follow = RemoteFollow.new
|
@remote_follow = RemoteFollow.new
|
||||||
|
@remote_follow.acct = session[:remote_follow] if session.key?(:remote_follow)
|
||||||
end
|
end
|
||||||
|
|
||||||
def create
|
def create
|
||||||
|
@ -22,6 +23,8 @@ class RemoteFollowController < ApplicationController
|
||||||
render(:new) && return
|
render(:new) && return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
session[:remote_follow] = @remote_follow.acct
|
||||||
|
|
||||||
redirect_to Addressable::Template.new(redirect_url_link.template).expand(uri: "#{@account.username}@#{Rails.configuration.x.local_domain}").to_s
|
redirect_to Addressable::Template.new(redirect_url_link.template).expand(uri: "#{@account.username}@#{Rails.configuration.x.local_domain}").to_s
|
||||||
else
|
else
|
||||||
render :new
|
render :new
|
||||||
|
|
|
@ -2,17 +2,30 @@
|
||||||
|
|
||||||
class EmailValidator < ActiveModel::EachValidator
|
class EmailValidator < ActiveModel::EachValidator
|
||||||
def validate_each(record, attribute, value)
|
def validate_each(record, attribute, value)
|
||||||
return if Rails.configuration.x.email_domains_blacklist.empty?
|
|
||||||
|
|
||||||
record.errors.add(attribute, I18n.t('users.invalid_email')) if blocked_email?(value)
|
record.errors.add(attribute, I18n.t('users.invalid_email')) if blocked_email?(value)
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def blocked_email?(value)
|
def blocked_email?(value)
|
||||||
|
on_blacklist?(value) || not_on_whitelist?(value)
|
||||||
|
end
|
||||||
|
|
||||||
|
def on_blacklist?(value)
|
||||||
|
return false if Rails.configuration.x.email_domains_blacklist.blank?
|
||||||
|
|
||||||
domains = Rails.configuration.x.email_domains_blacklist.gsub('.', '\.')
|
domains = Rails.configuration.x.email_domains_blacklist.gsub('.', '\.')
|
||||||
regexp = Regexp.new("@(.+\\.)?(#{domains})", true)
|
regexp = Regexp.new("@(.+\\.)?(#{domains})", true)
|
||||||
|
|
||||||
value =~ regexp
|
value =~ regexp
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def not_on_whitelist?(value)
|
||||||
|
return false if Rails.configuration.x.email_domains_whitelist.blank?
|
||||||
|
|
||||||
|
domains = Rails.configuration.x.email_domains_whitelist.gsub('.', '\.')
|
||||||
|
regexp = Regexp.new("@(.+\\.)?(#{domains})", true)
|
||||||
|
|
||||||
|
value !~ regexp
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -39,7 +39,7 @@ class FeedManager
|
||||||
|
|
||||||
def broadcast(timeline_id, options = {})
|
def broadcast(timeline_id, options = {})
|
||||||
options[:queued_at] = (Time.now.to_f * 1000.0).to_i
|
options[:queued_at] = (Time.now.to_f * 1000.0).to_i
|
||||||
ActionCable.server.broadcast("timeline:#{timeline_id}", options)
|
redis.publish("timeline:#{timeline_id}", Oj.dump(options))
|
||||||
end
|
end
|
||||||
|
|
||||||
def trim(type, account_id)
|
def trim(type, account_id)
|
||||||
|
@ -118,7 +118,7 @@ class FeedManager
|
||||||
|
|
||||||
def filter_from_mentions?(status, receiver_id)
|
def filter_from_mentions?(status, receiver_id)
|
||||||
check_for_blocks = [status.account_id]
|
check_for_blocks = [status.account_id]
|
||||||
check_for_blocks.concat(status.mentions.select('account_id').map(&:account_id))
|
check_for_blocks.concat(status.mentions.pluck(:account_id))
|
||||||
check_for_blocks.concat([status.in_reply_to_account]) if status.reply? && !status.in_reply_to_account_id.nil?
|
check_for_blocks.concat([status.in_reply_to_account]) if status.reply? && !status.in_reply_to_account_id.nil?
|
||||||
|
|
||||||
should_filter = receiver_id == status.account_id # Filter if I'm mentioning myself
|
should_filter = receiver_id == status.account_id # Filter if I'm mentioning myself
|
||||||
|
|
|
@ -3,9 +3,8 @@
|
||||||
class Block < ApplicationRecord
|
class Block < ApplicationRecord
|
||||||
include Paginable
|
include Paginable
|
||||||
|
|
||||||
belongs_to :account
|
belongs_to :account, required: true
|
||||||
belongs_to :target_account, class_name: 'Account'
|
belongs_to :target_account, class_name: 'Account', required: true
|
||||||
|
|
||||||
validates :account, :target_account, presence: true
|
|
||||||
validates :account_id, uniqueness: { scope: :target_account_id }
|
validates :account_id, uniqueness: { scope: :target_account_id }
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,11 +3,14 @@
|
||||||
class Follow < ApplicationRecord
|
class Follow < ApplicationRecord
|
||||||
include Paginable
|
include Paginable
|
||||||
|
|
||||||
belongs_to :account, counter_cache: :following_count
|
belongs_to :account, counter_cache: :following_count, required: true
|
||||||
belongs_to :target_account, class_name: 'Account', counter_cache: :followers_count
|
|
||||||
|
belongs_to :target_account,
|
||||||
|
class_name: 'Account',
|
||||||
|
counter_cache: :followers_count,
|
||||||
|
required: true
|
||||||
|
|
||||||
has_one :notification, as: :activity, dependent: :destroy
|
has_one :notification, as: :activity, dependent: :destroy
|
||||||
|
|
||||||
validates :account, :target_account, presence: true
|
|
||||||
validates :account_id, uniqueness: { scope: :target_account_id }
|
validates :account_id, uniqueness: { scope: :target_account_id }
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,12 +3,11 @@
|
||||||
class FollowRequest < ApplicationRecord
|
class FollowRequest < ApplicationRecord
|
||||||
include Paginable
|
include Paginable
|
||||||
|
|
||||||
belongs_to :account
|
belongs_to :account, required: true
|
||||||
belongs_to :target_account, class_name: 'Account'
|
belongs_to :target_account, class_name: 'Account', required: true
|
||||||
|
|
||||||
has_one :notification, as: :activity, dependent: :destroy
|
has_one :notification, as: :activity, dependent: :destroy
|
||||||
|
|
||||||
validates :account, :target_account, presence: true
|
|
||||||
validates :account_id, uniqueness: { scope: :target_account_id }
|
validates :account_id, uniqueness: { scope: :target_account_id }
|
||||||
|
|
||||||
def authorize!
|
def authorize!
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class Mention < ApplicationRecord
|
class Mention < ApplicationRecord
|
||||||
belongs_to :account, inverse_of: :mentions
|
belongs_to :account, inverse_of: :mentions, required: true
|
||||||
belongs_to :status
|
belongs_to :status, required: true
|
||||||
|
|
||||||
has_one :notification, as: :activity, dependent: :destroy
|
has_one :notification, as: :activity, dependent: :destroy
|
||||||
|
|
||||||
validates :account, :status, presence: true
|
|
||||||
validates :account, uniqueness: { scope: :status }
|
validates :account, uniqueness: { scope: :status }
|
||||||
end
|
end
|
||||||
|
|
|
@ -161,9 +161,9 @@ class Status < ApplicationRecord
|
||||||
return where.not(visibility: [:private, :direct]) if account.nil?
|
return where.not(visibility: [:private, :direct]) if account.nil?
|
||||||
|
|
||||||
if target_account.blocking?(account) # get rid of blocked peeps
|
if target_account.blocking?(account) # get rid of blocked peeps
|
||||||
where('1 = 0')
|
none
|
||||||
elsif account.id == target_account.id # author can see own stuff
|
elsif account.id == target_account.id # author can see own stuff
|
||||||
where('1 = 1')
|
all
|
||||||
elsif account.following?(target_account) # followers can see followers-only stuff, but also things they are mentioned in
|
elsif account.following?(target_account) # followers can see followers-only stuff, but also things they are mentioned in
|
||||||
joins('LEFT OUTER JOIN mentions ON statuses.id = mentions.status_id AND mentions.account_id = ' + account.id.to_s)
|
joins('LEFT OUTER JOIN mentions ON statuses.id = mentions.status_id AND mentions.account_id = ' + account.id.to_s)
|
||||||
.where('statuses.visibility != ? OR mentions.id IS NOT NULL', Status.visibilities[:direct])
|
.where('statuses.visibility != ? OR mentions.id IS NOT NULL', Status.visibilities[:direct])
|
||||||
|
|
5
app/workers/application_worker.rb
Normal file
5
app/workers/application_worker.rb
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
class ApplicationWorker
|
||||||
|
def info(message)
|
||||||
|
Rails.logger.info("#{self.class.name} - #{message}")
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,6 +1,6 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class DistributionWorker
|
class DistributionWorker < ApplicationWorker
|
||||||
include Sidekiq::Worker
|
include Sidekiq::Worker
|
||||||
|
|
||||||
def perform(status_id)
|
def perform(status_id)
|
||||||
|
@ -9,6 +9,6 @@ class DistributionWorker
|
||||||
FanOutOnWriteService.new.call(status)
|
FanOutOnWriteService.new.call(status)
|
||||||
WarmCacheService.new.call(status)
|
WarmCacheService.new.call(status)
|
||||||
rescue ActiveRecord::RecordNotFound
|
rescue ActiveRecord::RecordNotFound
|
||||||
true
|
info("Couldn't find the status")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,4 +2,5 @@
|
||||||
|
|
||||||
Rails.application.configure do
|
Rails.application.configure do
|
||||||
config.x.email_domains_blacklist = ENV.fetch('EMAIL_DOMAIN_BLACKLIST') { 'mvrht.com' }
|
config.x.email_domains_blacklist = ENV.fetch('EMAIL_DOMAIN_BLACKLIST') { 'mvrht.com' }
|
||||||
|
config.x.email_domains_whitelist = ENV.fetch('EMAIL_DOMAIN_WHITELIST') { '' }
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
---
|
---
|
||||||
de:
|
de:
|
||||||
about:
|
about:
|
||||||
about_mastodon: Mastodon ist ein <em>freier, quelloffener</em> soziales Netzwerkserver. Eine <em>dezentralisierte</em> Alternative zu kommerziellen Plattformen, verhindert es die Risiken, die entstehen, wenn eine einzelne Firma deine Kommunikation monopolisiert. Jeder kann Mastodon verwenden und ganz einfach am <em>sozialen Netzwerk</em> teilnehmen.
|
about_mastodon: Mastodon ist ein <em>freier, quelloffener</em> soziales Netzwerkserver. Als <em>dezentralisierte</em> Alternative zu kommerziellen Plattformen verhindert es die Risiken, die entstehen, wenn eine einzelne Firma deine Kommunikation monopolisiert. Jeder kann Mastodon verwenden und ganz einfach am <em>sozialen Netzwerk</em> teilnehmen.
|
||||||
get_started: Erste Schritte
|
get_started: Erste Schritte
|
||||||
source_code: Quellcode
|
source_code: Quellcode
|
||||||
terms: AGB
|
terms: AGB
|
||||||
accounts:
|
accounts:
|
||||||
follow: Folgen
|
follow: Folgen
|
||||||
followers: Folger
|
followers: Follower
|
||||||
following: Folgt
|
following: Gefolgt
|
||||||
nothing_here: Hier gibt es nichts!
|
nothing_here: Hier gibt es nichts!
|
||||||
people_followed_by: Nutzer, denen %{name} folgt
|
people_followed_by: Nutzer, denen %{name} folgt
|
||||||
people_who_follow: Nutzer, die %{name} folgen
|
people_who_follow: Nutzer, die %{name} folgen
|
||||||
|
@ -27,7 +27,7 @@ de:
|
||||||
reset_password: Passwort zurücksetzen
|
reset_password: Passwort zurücksetzen
|
||||||
set_new_password: Neues Passwort setzen
|
set_new_password: Neues Passwort setzen
|
||||||
authorize_follow:
|
authorize_follow:
|
||||||
error: Das entfernte Profil konnte nicht geladen werden
|
error: Das Profil konnte nicht geladen werden
|
||||||
follow: Folgen
|
follow: Folgen
|
||||||
prompt_html: 'Du (<strong>%{self}</strong>) möchtest dieser Person folgen:'
|
prompt_html: 'Du (<strong>%{self}</strong>) möchtest dieser Person folgen:'
|
||||||
title: "%{acct} folgen"
|
title: "%{acct} folgen"
|
||||||
|
@ -55,25 +55,25 @@ de:
|
||||||
notification_mailer:
|
notification_mailer:
|
||||||
favourite:
|
favourite:
|
||||||
body: 'Dein Beitrag wurde von %{name} favorisiert:'
|
body: 'Dein Beitrag wurde von %{name} favorisiert:'
|
||||||
subject: "%{name} hat deinen Beitrag favorisiert"
|
subject: "%{name} hat deinen Beitrag favorisiert."
|
||||||
follow:
|
follow:
|
||||||
body: "%{name} folgt dir jetzt!"
|
body: "%{name} folgt dir jetzt!"
|
||||||
subject: "%{name} folgt dir nun"
|
subject: "%{name} folgt dir jetzt."
|
||||||
follow_request:
|
follow_request:
|
||||||
body: "%{name} möchte dir folgen:"
|
body: "%{name} möchte dir folgen:"
|
||||||
subject: "%{name} möchte dir folgen"
|
subject: "%{name} möchte dir folgen."
|
||||||
mention:
|
mention:
|
||||||
body: "%{name} hat dich erwähnt:"
|
body: "%{name} hat dich erwähnt:"
|
||||||
subject: "%{name} hat dich erwähnt"
|
subject: "%{name} hat dich erwähnt."
|
||||||
reblog:
|
reblog:
|
||||||
body: 'Dein Beitrag wurde von %{name} geteilt:'
|
body: 'Dein Beitrag wurde von %{name} geteilt:'
|
||||||
subject: "%{name} teilte deinen Beitrag"
|
subject: "%{name} teilte deinen Beitrag."
|
||||||
pagination:
|
pagination:
|
||||||
next: Vorwärts
|
next: Vorwärts
|
||||||
prev: Zurück
|
prev: Zurück
|
||||||
remote_follow:
|
remote_follow:
|
||||||
acct: Dein Nutzername@Domain, von dem du dieser Person folgen möchtest
|
acct: Dein Nutzername@Domain, von dem aus du dieser Person folgen möchtest.
|
||||||
missing_resource: Die erforderliche Weiterleitungs-URL konnte leider in deinem Profil nicht gefunden werden
|
missing_resource: Die erforderliche Weiterleitungs-URL konnte leider in deinem Profil nicht gefunden werden.
|
||||||
proceed: Weiter
|
proceed: Weiter
|
||||||
prompt: 'Du wirst dieser Person folgen:'
|
prompt: 'Du wirst dieser Person folgen:'
|
||||||
settings:
|
settings:
|
||||||
|
|
|
@ -2,59 +2,59 @@
|
||||||
de:
|
de:
|
||||||
devise:
|
devise:
|
||||||
confirmations:
|
confirmations:
|
||||||
confirmed: "Vielen Dank für Deine Registrierung. Bitte melde dich jetzt an."
|
confirmed: "Vielen Dank für deine Registrierung. Bitte melde dich jetzt an."
|
||||||
send_instructions: "Du erhältst in wenigen Minuten eine E-Mail, mit der Du Deine Registrierung bestätigen kannst."
|
send_instructions: "Du erhältst in wenigen Minuten eine E-Mail, mit der du deine Registrierung bestätigen kannst."
|
||||||
send_paranoid_instructions: "Falls Deine E-Mail-Adresse in unserer Datenbank existiert erhältst Du in wenigen Minuten eine E-Mail mit der Du Deine Registrierung bestätigen kannst."
|
send_paranoid_instructions: "Falls Deine E-Mail-Adresse in unserer Datenbank existiert, erhältst Du in wenigen Minuten eine E-Mail mit der du deine Registrierung bestätigen kannst."
|
||||||
failure:
|
failure:
|
||||||
already_authenticated: "Du bist bereits angemeldet."
|
already_authenticated: "Du bist bereits angemeldet."
|
||||||
inactive: "Dein Account ist nicht aktiv."
|
inactive: "Dein Account ist nicht aktiv."
|
||||||
invalid: "Ungültige Anmeldedaten."
|
invalid: "Ungültige Anmeldedaten."
|
||||||
last_attempt: "Du hast noch einen Versuch bevor dein Account gesperrt wird"
|
last_attempt: "Du hast noch einen Versuch bevor dein Account gesperrt wird."
|
||||||
locked: "Dein Account ist gesperrt."
|
locked: "Dein Account ist gesperrt."
|
||||||
not_found_in_database: "E-Mail-Adresse oder Passwort ungültig."
|
not_found_in_database: "E-Mail-Adresse oder Passwort ungültig."
|
||||||
timeout: "Deine Sitzung ist abgelaufen, bitte melde Dich erneut an."
|
timeout: "Deine Sitzung ist abgelaufen, bitte melde dich erneut an."
|
||||||
unauthenticated: "Du musst Dich anmelden oder registrieren, bevor Du fortfahren kannst."
|
unauthenticated: "Du musst Dich anmelden oder registrieren, bevor du fortfahren kannst."
|
||||||
unconfirmed: "Du musst Deinen Account bestätigen, bevor Du fortfahren kannst."
|
unconfirmed: "Du musst deinen Account bestätigen, bevor du fortfahren kannst."
|
||||||
mailer:
|
mailer:
|
||||||
confirmation_instructions:
|
confirmation_instructions:
|
||||||
subject: "Mastodon: Anleitung zur Bestätigung Deines Accounts"
|
subject: "Mastodon: Anleitung zur Bestätigung deines Accounts"
|
||||||
password_change:
|
password_change:
|
||||||
subject: 'Mastodon: Passwort wurde geändert'
|
subject: 'Mastodon: Passwort wurde geändert'
|
||||||
reset_password_instructions:
|
reset_password_instructions:
|
||||||
subject: "Mastodon: Anleitung um Dein Passwort zurückzusetzen"
|
subject: "Mastodon: Anleitung um dein Passwort zurückzusetzen"
|
||||||
unlock_instructions:
|
unlock_instructions:
|
||||||
subject: "Mastodon: Anleitung um Deinen Account freizuschalten"
|
subject: "Mastodon: Anleitung um deinen Account freizuschalten"
|
||||||
omniauth_callbacks:
|
omniauth_callbacks:
|
||||||
failure: "Du konntest nicht Deinem %{kind}-Account angemeldet werden, weil '%{reason}'."
|
failure: "Du konntest nicht mit deinem %{kind}-Account angemeldet werden, weil '%{reason}'."
|
||||||
success: "Du hast Dich erfolgreich mit Deinem %{kind}-Account angemeldet."
|
success: "Du hast dich erfolgreich mit Deinem %{kind}-Account angemeldet."
|
||||||
passwords:
|
passwords:
|
||||||
no_token: "Du kannst diese Seite nur von dem Link aus einer E-Mail zum Passwort-Zurücksetzen aufrufen. Wenn du einen solchen Link aufgerufen hast stelle bitte sicher, dass du die vollständige Adresse aufrufst."
|
no_token: "Du kannst diese Seite nur über den Link aus der E-Mail zum Passwort-Zurücksetzen aufrufen. Wenn du einen solchen Link aufgerufen hast, stelle bitte sicher, dass du die vollständige Adresse aufrufst."
|
||||||
send_instructions: "Du erhältst in wenigen Minuten eine E-Mail mit der Anleitung, wie Du Dein Passwort zurücksetzen kannst."
|
send_instructions: "Du erhältst in wenigen Minuten eine E-Mail mit der Anleitung, wie du dein Passwort zurücksetzen kannst."
|
||||||
send_paranoid_instructions: "Falls Deine E-Mail-Adresse in unserer Datenbank existiert erhältst Du in wenigen Minuten eine E-Mail mit der Anleitung, wie Du Dein Passwort zurücksetzen können."
|
send_paranoid_instructions: "Falls deine E-Mail-Adresse in unserer Datenbank existiert erhältst du in wenigen Minuten eine E-Mail mit der Anleitung, wie du dein Passwort zurücksetzen kannst."
|
||||||
updated: "Dein Passwort wurde geändert. Du bist jetzt angemeldet."
|
updated: "Dein Passwort wurde geändert. Du bist jetzt angemeldet."
|
||||||
updated_not_active: "Dein Passwort wurde geändert."
|
updated_not_active: "Dein Passwort wurde geändert."
|
||||||
registrations:
|
registrations:
|
||||||
destroyed: "Dein Account wurde gelöscht."
|
destroyed: "Dein Account wurde gelöscht."
|
||||||
signed_up: "Du hast dich erfolgreich registriert."
|
signed_up: "Du hast dich erfolgreich registriert."
|
||||||
signed_up_but_inactive: "Du hast dich erfolgreich registriert. Wir konnten Dich noch nicht anmelden, da Dein Account inaktiv ist."
|
signed_up_but_inactive: "Du hast dich erfolgreich registriert. Wir konnten dich noch nicht anmelden, da dein Account inaktiv ist."
|
||||||
signed_up_but_locked: "Du hast dich erfolgreich registriert. Wir konnten Dich noch nicht anmelden, da Dein Account gesperrt ist."
|
signed_up_but_locked: "Du hast dich erfolgreich registriert. Wir konnten dich noch nicht anmelden, da dein Account gesperrt ist."
|
||||||
signed_up_but_unconfirmed: "Du hast Dich erfolgreich registriert. Wir konnten Dich noch nicht anmelden, da Dein Account noch nicht bestätigt ist. Du erhältst in Kürze eine E-Mail mit der Anleitung, wie Du Deinen Account freischalten kannst."
|
signed_up_but_unconfirmed: "Du hast Dich erfolgreich registriert. Wir konnten dich noch nicht anmelden, da dein Account noch nicht bestätigt ist. Du erhältst in Kürze eine E-Mail mit der Anleitung, wie Du Deinen Account freischalten kannst."
|
||||||
update_needs_confirmation: "Deine Daten wurden aktualisiert, aber Du musst Deine neue E-Mail-Adresse bestätigen. Du erhälst in wenigen Minuten eine E-Mail, mit der Du die Änderung Deiner E-Mail-Adresse abschließen kannst."
|
update_needs_confirmation: "Deine Daten wurden aktualisiert, aber du musst deine neue E-Mail-Adresse bestätigen. Du erhälst in wenigen Minuten eine E-Mail, mit der du die Änderung deiner E-Mail-Adresse abschließen kannst."
|
||||||
updated: "Deine Daten wurden aktualisiert."
|
updated: "Deine Daten wurden aktualisiert."
|
||||||
sessions:
|
sessions:
|
||||||
already_signed_out: "Erfolgreich abgemeldet."
|
already_signed_out: "Erfolgreich abgemeldet."
|
||||||
signed_in: "Erfolgreich angemeldet."
|
signed_in: "Erfolgreich angemeldet."
|
||||||
signed_out: "Erfolgreich abgemeldet."
|
signed_out: "Erfolgreich abgemeldet."
|
||||||
unlocks:
|
unlocks:
|
||||||
send_instructions: "Du erhältst in wenigen Minuten eine E-Mail mit der Anleitung, wie Du Deinen Account entsperren können."
|
send_instructions: "Du erhältst in wenigen Minuten eine E-Mail mit der Anleitung, wie du deinen Account entsperren können."
|
||||||
send_paranoid_instructions: "Falls Deine E-Mail-Adresse in unserer Datenbank existiert erhältst Du in wenigen Minuten eine E-Mail mit der Anleitung, wie Du Deinen Account entsperren kannst."
|
send_paranoid_instructions: "Falls deine E-Mail-Adresse in unserer Datenbank existiert erhältst du in wenigen Minuten eine E-Mail mit der Anleitung, wie du deinen Account entsperren kannst."
|
||||||
unlocked: "Dein Account wurde entsperrt. Du bist jetzt angemeldet."
|
unlocked: "Dein Account wurde entsperrt. Du bist jetzt angemeldet."
|
||||||
errors:
|
errors:
|
||||||
messages:
|
messages:
|
||||||
already_confirmed: "wurde bereits bestätigt"
|
already_confirmed: "wurde bereits bestätigt."
|
||||||
confirmation_period_expired: "muss innerhalb %{period} bestätigt werden, bitte fordere einen neuen Link an"
|
confirmation_period_expired: "muss innerhalb %{period} bestätigt werden, bitte fordere einen neuen Link an."
|
||||||
expired: "ist abgelaufen, bitte neu anfordern"
|
expired: "ist abgelaufen, bitte neu anfordern."
|
||||||
not_found: "nicht gefunden"
|
not_found: "wurde nicht gefunden."
|
||||||
not_locked: "ist nicht gesperrt"
|
not_locked: "ist nicht gesperrt"
|
||||||
not_saved:
|
not_saved:
|
||||||
one: "Konnte %{resource} nicht speichern: ein Fehler."
|
one: "Konnte %{resource} nicht speichern: ein Fehler."
|
||||||
|
|
|
@ -62,7 +62,7 @@ fr:
|
||||||
buttons:
|
buttons:
|
||||||
revoke: Annuler
|
revoke: Annuler
|
||||||
confirmations:
|
confirmations:
|
||||||
revoke: Êtes-vous certain?
|
revoke: Êtes-vous certain ?
|
||||||
index:
|
index:
|
||||||
application: Application
|
application: Application
|
||||||
created_at: Créé le
|
created_at: Créé le
|
||||||
|
@ -72,19 +72,19 @@ fr:
|
||||||
errors:
|
errors:
|
||||||
messages:
|
messages:
|
||||||
access_denied: Le propriétaire de la ressource ou le serveur d'autorisation a refusé la demande.
|
access_denied: Le propriétaire de la ressource ou le serveur d'autorisation a refusé la demande.
|
||||||
credential_flow_not_configured: Le flux des identifiants du mot de passe du propriétaire de la ressource a échoué en raison de Doorkeeper.configure.resource_owner_from_credentials n'est pas configuré.
|
credential_flow_not_configured: Le flux des identifiants du mot de passe du propriétaire de la ressource a échoué car Doorkeeper.configure.resource_owner_from_credentials n'est pas configuré.
|
||||||
invalid_client: L'authentification du client a échoué à cause d'un client inconnu, d'aucune authentification de client incluse, ou d'une méthode d'authentification non prise en charge.
|
invalid_client: L'authentification du client a échoué à cause d'un client inconnu, d'aucune authentification de client incluse, ou d'une méthode d'authentification non prise en charge.
|
||||||
invalid_grant: Le consentement d'autorisation accordé n'est pas valide, a expiré, est annulé, ne concorde pas avec l'URL de redirection utilisée dans la demande d'autorisation, ou a été émis à un autre client.
|
invalid_grant: Le consentement d'autorisation accordé n'est pas valide, a expiré, est annulé, ne concorde pas avec l'URL de redirection utilisée dans la demande d'autorisation, ou a été émis à un autre client.
|
||||||
invalid_redirect_uri: L'URL de redirection n'est pas valide.
|
invalid_redirect_uri: L'URL de redirection n'est pas valide.
|
||||||
invalid_request: La demande manque un paramètre requis, inclut une valeur de paramètre non prise en charge, ou est autrement mal formée.
|
invalid_request: La demande manque un paramètre requis, inclut une valeur de paramètre non prise en charge, ou est autrement mal formée.
|
||||||
invalid_resource_owner: Les identifiants fournis du propriétaire de la ressource ne sont pas valides, ou le propriétaire de la ressource ne peut être trouvé
|
invalid_resource_owner: Les identifiants fournis par le propriétaire de la ressource ne sont pas valides, ou le propriétaire de la ressource ne peut être trouvé
|
||||||
invalid_scope: La portée demandée n'est pas valide, est inconnue, ou est mal formée.
|
invalid_scope: La portée demandée n'est pas valide, est inconnue, ou est mal formée.
|
||||||
invalid_token:
|
invalid_token:
|
||||||
expired: Le jeton d'accès a expiré
|
expired: Le jeton d'accès a expiré
|
||||||
revoked: Le jeton d'accès a été révoqué
|
revoked: Le jeton d'accès a été révoqué
|
||||||
unknown: Le jeton d'accès n'est pas valide
|
unknown: Le jeton d'accès n'est pas valide
|
||||||
resource_owner_authenticator_not_configured: La recherche du propriétaire de la ressource a échoué en raison de Doorkeeper.configure.resource_owner_authenticator n'est pas configuré.
|
resource_owner_authenticator_not_configured: La recherche du propriétaire de la ressource a échoué car Doorkeeper.configure.resource_owner_authenticator n'est pas configuré.
|
||||||
server_error: Le serveur d'autorisation a rencontré une condition inattendue qui l'a empêché de remplir la demande.
|
server_error: Le serveur d'autorisation a rencontré une condition inattendue l'empêchant de remplir la demande.
|
||||||
temporarily_unavailable: Le serveur d'autorisation est actuellement incapable de traiter la demande à cause d'une surcharge ou d'un entretien temporaire du serveur.
|
temporarily_unavailable: Le serveur d'autorisation est actuellement incapable de traiter la demande à cause d'une surcharge ou d'un entretien temporaire du serveur.
|
||||||
unauthorized_client: Le client n'est pas autorisé à effectuer cette demande à l'aide de cette méthode.
|
unauthorized_client: Le client n'est pas autorisé à effectuer cette demande à l'aide de cette méthode.
|
||||||
unsupported_grant_type: Le type de consentement d'autorisation n'est pas pris en charge par le serveur d'autorisation.
|
unsupported_grant_type: Le type de consentement d'autorisation n'est pas pris en charge par le serveur d'autorisation.
|
||||||
|
|
|
@ -5,8 +5,8 @@ en:
|
||||||
about_this: About this instance
|
about_this: About this instance
|
||||||
apps: Apps
|
apps: Apps
|
||||||
business_email: 'Business e-mail:'
|
business_email: 'Business e-mail:'
|
||||||
contact: Contact
|
|
||||||
closed_registrations: Registrations are currently closed on this instance.
|
closed_registrations: Registrations are currently closed on this instance.
|
||||||
|
contact: Contact
|
||||||
description_headline: What is %{domain}?
|
description_headline: What is %{domain}?
|
||||||
domain_count_after: other instances
|
domain_count_after: other instances
|
||||||
domain_count_before: Connected to
|
domain_count_before: Connected to
|
||||||
|
|
|
@ -5,6 +5,7 @@ fr:
|
||||||
about_this: À propos de cette instance
|
about_this: À propos de cette instance
|
||||||
apps: Applications
|
apps: Applications
|
||||||
business_email: E-mail professionnel
|
business_email: E-mail professionnel
|
||||||
|
closed_registrations: Les inscriptions sont actuellement fermées sur cette instance. .
|
||||||
description_headline: Qu'est-ce que %{domain} ?
|
description_headline: Qu'est-ce que %{domain} ?
|
||||||
domain_count_after: autres instances
|
domain_count_after: autres instances
|
||||||
domain_count_before: Connectés à
|
domain_count_before: Connectés à
|
||||||
|
|
|
@ -38,7 +38,7 @@ en:
|
||||||
follow: Send e-mail when someone follows you
|
follow: Send e-mail when someone follows you
|
||||||
follow_request: Send e-mail when someone requests to follow you
|
follow_request: Send e-mail when someone requests to follow you
|
||||||
mention: Send e-mail when someone mentions you
|
mention: Send e-mail when someone mentions you
|
||||||
reblog: Send e-mail when someone reblogs your status
|
reblog: Send e-mail when someone boosts your status
|
||||||
'no': 'No'
|
'no': 'No'
|
||||||
required:
|
required:
|
||||||
mark: "*"
|
mark: "*"
|
||||||
|
|
|
@ -6,7 +6,7 @@ fi:
|
||||||
avatar: PNG, GIF tai JPG. Korkeintaan 2MB. Skaalataan kokoon 120x120px
|
avatar: PNG, GIF tai JPG. Korkeintaan 2MB. Skaalataan kokoon 120x120px
|
||||||
display_name: Korkeintaan 30 merkkiä
|
display_name: Korkeintaan 30 merkkiä
|
||||||
header: PNG, GIF tai JPG. Korkeintaan 2MB. Skaalataan kokoon 700x335px
|
header: PNG, GIF tai JPG. Korkeintaan 2MB. Skaalataan kokoon 700x335px
|
||||||
locked: Vaatii sinun manuaalisesti hyväksymään seuraajat ja asettaa julkaisun yksityisyyden vain seuraajille
|
locked: Vaatii sinun manuaalisesti hyväksymään seuraajat ja asettaa julkaisujen yksityisyyden vain seuraajille
|
||||||
note: Korkeintaan 160 merkkiä
|
note: Korkeintaan 160 merkkiä
|
||||||
imports:
|
imports:
|
||||||
data: CSV tiedosto tuotu toiselta Mastodon palvelimelta
|
data: CSV tiedosto tuotu toiselta Mastodon palvelimelta
|
||||||
|
@ -17,7 +17,7 @@ fi:
|
||||||
confirm_password: Varmista salasana
|
confirm_password: Varmista salasana
|
||||||
current_password: Nykyinen salasana
|
current_password: Nykyinen salasana
|
||||||
data: Data
|
data: Data
|
||||||
display_name: Näyttö nimi
|
display_name: Näykyvä nimi
|
||||||
email: Sähköpostiosoite
|
email: Sähköpostiosoite
|
||||||
header: Header
|
header: Header
|
||||||
locale: Kieli
|
locale: Kieli
|
||||||
|
@ -38,7 +38,7 @@ fi:
|
||||||
follow: Lähetä s-posti kun joku seuraa sinua
|
follow: Lähetä s-posti kun joku seuraa sinua
|
||||||
follow_request: Lähetä s-posti kun joku pyytää seurata sinua
|
follow_request: Lähetä s-posti kun joku pyytää seurata sinua
|
||||||
mention: Lähetä s-posti kun joku mainitsee sinut
|
mention: Lähetä s-posti kun joku mainitsee sinut
|
||||||
reblog: Lähetä s-posti kun joku uudestaanblogaa julkaisusi
|
reblog: Lähetä s-posti kun joku buustaa julkaisusi
|
||||||
'no': 'Ei'
|
'no': 'Ei'
|
||||||
required:
|
required:
|
||||||
mark: "*"
|
mark: "*"
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
class AddIndexOnMentionsStatusId < ActiveRecord::Migration[5.0]
|
||||||
|
def change
|
||||||
|
add_index :mentions, :status_id
|
||||||
|
end
|
||||||
|
end
|
|
@ -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: 20170403172249) do
|
ActiveRecord::Schema.define(version: 20170405112956) 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"
|
||||||
|
@ -127,6 +127,7 @@ ActiveRecord::Schema.define(version: 20170403172249) do
|
||||||
t.datetime "created_at", null: false
|
t.datetime "created_at", null: false
|
||||||
t.datetime "updated_at", null: false
|
t.datetime "updated_at", null: false
|
||||||
t.index ["account_id", "status_id"], name: "index_mentions_on_account_id_and_status_id", unique: true, using: :btree
|
t.index ["account_id", "status_id"], name: "index_mentions_on_account_id_and_status_id", unique: true, using: :btree
|
||||||
|
t.index ["status_id"], name: "index_mentions_on_status_id", using: :btree
|
||||||
end
|
end
|
||||||
|
|
||||||
create_table "mutes", force: :cascade do |t|
|
create_table "mutes", force: :cascade do |t|
|
||||||
|
|
|
@ -7,7 +7,7 @@ So, you have a working Mastodon instance... now what?
|
||||||
|
|
||||||
The following rake task:
|
The following rake task:
|
||||||
|
|
||||||
rails mastodon:make_admin USERNAME=alice
|
rake mastodon:make_admin USERNAME=alice
|
||||||
|
|
||||||
Would turn the local user "alice" into an admin.
|
Would turn the local user "alice" into an admin.
|
||||||
|
|
||||||
|
|
|
@ -11,3 +11,5 @@ Mastodon can theoretically run indefinitely on a free [Heroku](https://heroku.co
|
||||||
* You will want Amazon S3 for file storage. The only exception is for development purposes, where you may not care if files are not saved. Follow a guide online for creating a free Amazon S3 bucket and Access Key, then enter the details.
|
* You will want Amazon S3 for file storage. The only exception is for development purposes, where you may not care if files are not saved. Follow a guide online for creating a free Amazon S3 bucket and Access Key, then enter the details.
|
||||||
* If you want your Mastodon to be able to send emails, configure SMTP settings here (or later). Consider using [Mailgun](https://mailgun.com) or similar, who offer free plans that should suit your interests.
|
* If you want your Mastodon to be able to send emails, configure SMTP settings here (or later). Consider using [Mailgun](https://mailgun.com) or similar, who offer free plans that should suit your interests.
|
||||||
3. Deploy! The app should be set up, with a working web interface and database. You can change settings and manage versions from the Heroku dashboard.
|
3. Deploy! The app should be set up, with a working web interface and database. You can change settings and manage versions from the Heroku dashboard.
|
||||||
|
|
||||||
|
You may need to use the `heroku` CLI application to run `USERNAME=yourUsername rails mastodon:make_admin` to make yourself an admin.
|
||||||
|
|
|
@ -11,10 +11,23 @@ map $http_upgrade $connection_upgrade {
|
||||||
'' close;
|
'' close;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
listen [::]:80;
|
||||||
|
server_name example.com;
|
||||||
|
return 301 https://$host$request_uri;
|
||||||
|
}
|
||||||
|
|
||||||
server {
|
server {
|
||||||
listen 443 ssl;
|
listen 443 ssl;
|
||||||
server_name example.com;
|
server_name example.com;
|
||||||
|
|
||||||
|
ssl_protocols TLSv1.2;
|
||||||
|
ssl_ciphers EECDH+AESGCM:EECDH+AES;
|
||||||
|
ssl_ecdh_curve secp384r1;
|
||||||
|
ssl_prefer_server_ciphers on;
|
||||||
|
ssl_session_cache shared:SSL:10m;
|
||||||
|
|
||||||
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
|
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
|
||||||
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
|
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
|
||||||
|
|
||||||
|
@ -76,7 +89,7 @@ It is recommended to create a special user for mastodon on the server (you could
|
||||||
## General dependencies
|
## General dependencies
|
||||||
|
|
||||||
curl -sL https://deb.nodesource.com/setup_4.x | sudo bash -
|
curl -sL https://deb.nodesource.com/setup_4.x | sudo bash -
|
||||||
sudo apt-get install imagemagick ffmpeg libpq-dev libxml2-dev libxslt1-dev nodejs
|
sudo apt-get install imagemagick ffmpeg libpq-dev libxml2-dev libxslt1-dev nodejs file
|
||||||
sudo npm install -g yarn
|
sudo npm install -g yarn
|
||||||
|
|
||||||
## Redis
|
## Redis
|
||||||
|
@ -112,7 +125,7 @@ Then once `rbenv` is ready, run `rbenv install 2.3.1` to install the Ruby versio
|
||||||
You need the `git-core` package installed on your system. If it is so, from the `mastodon` user:
|
You need the `git-core` package installed on your system. If it is so, from the `mastodon` user:
|
||||||
|
|
||||||
cd ~
|
cd ~
|
||||||
git clone https://github.com/Gargron/mastodon.git live
|
git clone https://github.com/tootsuite/mastodon.git live
|
||||||
cd live
|
cd live
|
||||||
|
|
||||||
Then you can proceed to install project dependencies:
|
Then you can proceed to install project dependencies:
|
||||||
|
@ -132,7 +145,7 @@ Fill in the important data, like host/port of the redis database, host/port/user
|
||||||
|
|
||||||
rake secret
|
rake secret
|
||||||
|
|
||||||
To get a random string. If you are setting up on one single server (most likely), then REDIS_HOST is localhost and `DB_HOST` is `/var/run/postgresql`, `DB_USER` is `mastodon` and `DB_NAME` is `mastodon_production` while `DB_PASS` is empty because this setup will use the ident authentication method (system user "mastodon" maps to postgres user "mastodon").
|
To get a random string. If you are setting up on one single server (most likely), then `REDIS_HOST` is localhost and `DB_HOST` is `/var/run/postgresql`, `DB_USER` is `mastodon` and `DB_NAME` is `mastodon_production` while `DB_PASS` is empty because this setup will use the ident authentication method (system user "mastodon" maps to postgres user "mastodon").
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
@ -221,7 +234,7 @@ I recommend creating a couple cronjobs for the following tasks:
|
||||||
|
|
||||||
You may want to run `which bundle` first and copypaste that full path instead of simply `bundle` in the above commands because cronjobs usually don't have all the paths set. The time and intervals of when to run these jobs are up to you, but once every day should be enough for all.
|
You may want to run `which bundle` first and copypaste that full path instead of simply `bundle` in the above commands because cronjobs usually don't have all the paths set. The time and intervals of when to run these jobs are up to you, but once every day should be enough for all.
|
||||||
|
|
||||||
You can edit the cronjob file for the `mastodon` user by running `sudo crontab -e mastodon` (outside of the mastodon user).
|
You can edit the cronjob file for the `mastodon` user by running `sudo crontab -e -u mastodon` (outside of the mastodon user).
|
||||||
|
|
||||||
## Things to look out for when upgrading Mastodon
|
## Things to look out for when upgrading Mastodon
|
||||||
|
|
||||||
|
|
|
@ -5,27 +5,32 @@ There is also a list at [instances.mastodon.xyz](https://instances.mastodon.xyz)
|
||||||
|
|
||||||
| Name | Theme/Notes, if applicable | Open Registrations | IPv6 |
|
| Name | Theme/Notes, if applicable | Open Registrations | IPv6 |
|
||||||
| -------------|-------------|---|---|
|
| -------------|-------------|---|---|
|
||||||
| [mastodon.social](https://mastodon.social) |Flagship, quick updates|Yes|No|
|
| [mastodon.social](https://mastodon.social) |Flagship, quick updates|No|No|
|
||||||
|
| [securitymastod.one](https://securitymastod.one/) |Information security enthusiasts and pros|Yes|Yes|
|
||||||
|
| [mastodon.cx](https://mastodon.cx/) |Alternative Mastodon instance hosted in France|Yes|Yes|
|
||||||
|
| [mastodon.network](https://mastodon.network) |N/A|Yes|Yes|
|
||||||
| [awoo.space](https://awoo.space) |Intentionally moderated, only federates with mastodon.social|Yes|No|
|
| [awoo.space](https://awoo.space) |Intentionally moderated, only federates with mastodon.social|Yes|No|
|
||||||
| [social.tchncs.de](https://social.tchncs.de)|N/A|Yes|No|
|
|
||||||
| [animalliberation.social](https://animalliberation.social) |Animal Rights|Yes|No|
|
| [animalliberation.social](https://animalliberation.social) |Animal Rights|Yes|No|
|
||||||
| [socially.constructed.space](https://socially.constructed.space) |Single user|No|No|
|
| [socially.constructed.space](https://socially.constructed.space) |Single user|No|No|
|
||||||
| [epiktistes.com](https://epiktistes.com) |N/A|Yes|No|
|
| [epiktistes.com](https://epiktistes.com) |N/A|Yes|No|
|
||||||
| [fern.surgeplay.com](https://fern.surgeplay.com) |Federates everywhere, Minecraft-focused|Yes|No
|
| [fern.surgeplay.com](https://fern.surgeplay.com) |Federates everywhere, Minecraft-focused|Yes|No
|
||||||
| [gay.crime.team](https://gay.crime.team) |the place for doin' gay crime online (please don't actually do crime here)|Yes|No|
|
| [gay.crime.team](https://gay.crime.team) |the place for doin' gay crime online (please don't actually do crime here)|No|No|
|
||||||
| [icosahedron.website](https://icosahedron.website/) |Icosahedron-themed (well, visually), open registration.|Yes|No|
|
| [icosahedron.website](https://icosahedron.website/) |Icosahedron-themed (well, visually), open registration.|Yes|No|
|
||||||
| [memetastic.space](https://memetastic.space) |Memes|Yes|No|
|
| [memetastic.space](https://memetastic.space) |Memes|Yes|No|
|
||||||
| [social.diskseven.com](https://social.diskseven.com) |Single user|No|No (DNS entry but no response)|
|
| [social.diskseven.com](https://social.diskseven.com) |Single user|No|Yes|
|
||||||
| [social.gestaltzerfall.net](https://social.gestaltzerfall.net) |Single user|No|No|
|
| [social.gestaltzerfall.net](https://social.gestaltzerfall.net) |Single user|No|No|
|
||||||
| [mastodon.xyz](https://mastodon.xyz) |N/A|Yes|Yes|
|
| [mastodon.xyz](https://mastodon.xyz) |N/A|Yes|Yes|
|
||||||
|
| [mastodon.partipirate.org](https://mastodon.partipirate.org) |French Pirate Part Instance - Politics and stuff|Yes|No|
|
||||||
| [social.targaryen.house](https://social.targaryen.house) |Federates everywhere, quick updates.|Yes|Yes|
|
| [social.targaryen.house](https://social.targaryen.house) |Federates everywhere, quick updates.|Yes|Yes|
|
||||||
| [social.mashek.net](https://social.mashek.net) |Themed and customised for Mashekstein Labs community. Selectively federates.|Yes|No|
|
|
||||||
| [masto.themimitoof.fr](https://masto.themimitoof.fr) |N/A|Yes|Yes|
|
| [masto.themimitoof.fr](https://masto.themimitoof.fr) |N/A|Yes|Yes|
|
||||||
|
| [mstdn.io](https://mstdn.io) |N/A|Yes|Yes|
|
||||||
| [social.imirhil.fr](https://social.imirhil.fr) |N/A|No|Yes|
|
| [social.imirhil.fr](https://social.imirhil.fr) |N/A|No|Yes|
|
||||||
| [social.wxcafe.net](https://social.wxcafe.net) |Open registrations, federates everywhere, no moderation yet|Yes|Yes|
|
| [social.wxcafe.net](https://social.wxcafe.net) |Open registrations, federates everywhere, no moderation yet|Yes|Yes|
|
||||||
| [octodon.social](https://octodon.social) |Open registrations, federates everywhere, cutest instance yet|Yes|Yes|
|
| [octodon.social](https://octodon.social) |Open registrations, federates everywhere, cutest instance yet|Yes|Yes|
|
||||||
|
| [mastodon.club](https://mastodon.club)|Open Registration, Open Federation, Mostly Canadians|Yes|No|
|
||||||
| [hostux.social](https://hostux.social) |N/A|Yes|Yes|
|
| [hostux.social](https://hostux.social) |N/A|Yes|Yes|
|
||||||
| [social.alex73630.xyz](https://social.alex73630.xyz) |Francophones|Yes|Yes|
|
| [social.alex73630.xyz](https://social.alex73630.xyz) |Francophones|Yes|Yes|
|
||||||
|
| [oc.todon.fr](https://oc.todon.fr) |Modérée et principalement francophone, pas de tolérances pour misogynie/LGBTphobies/validisme/etc.|Yes|Yes|
|
||||||
| [maly.io](https://maly.io) |N/A|Yes|No|
|
| [maly.io](https://maly.io) |N/A|Yes|No|
|
||||||
| [social.lou.lt](https://social.lou.lt) |N/A|Yes|No|
|
| [social.lou.lt](https://social.lou.lt) |N/A|Yes|No|
|
||||||
| [mastodon.ninetailed.uk](https://mastodon.ninetailed.uk) |N/A|Yes|No|
|
| [mastodon.ninetailed.uk](https://mastodon.ninetailed.uk) |N/A|Yes|No|
|
||||||
|
@ -36,6 +41,10 @@ There is also a list at [instances.mastodon.xyz](https://instances.mastodon.xyz)
|
||||||
| [share.elouworld.org](https://share.elouworld.org)|N/A|No|No|
|
| [share.elouworld.org](https://share.elouworld.org)|N/A|No|No|
|
||||||
| [social.lkw.tf](https://social.lkw.tf)|N/A|No|No|
|
| [social.lkw.tf](https://social.lkw.tf)|N/A|No|No|
|
||||||
| [manowar.social](https://manowar.social)|N/A|No|No|
|
| [manowar.social](https://manowar.social)|N/A|No|No|
|
||||||
| [social.ballpointcarrot.net](https://social.ballpointcarrot.net)|Down at time of entry|No|No|
|
| [social.ballpointcarrot.net](https://social.ballpointcarrot.net)|N/A|No|No|
|
||||||
|
| [social.nasqueron.org](https://social.nasqueron.org) |Dreamers, open source developers, free culture|Yes|Yes|
|
||||||
|
| [status.dissidence.ovh](https://status.dissidence.ovh)|N/A|Yes|Yes|
|
||||||
|
| [mastodon.cc](https://mastodon.cc)|Art|Yes|No|
|
||||||
|
| [mastodon.technology](https://mastodon.technology)|Open registrations, federates everywhere, for tech folks|Yes|No|
|
||||||
|
|
||||||
Let me know if you start running one so I can add it to the list! (Alternatively, add it yourself as a pull request).
|
Let me know if you start running one so I can add it to the list! (Alternatively, add it yourself as a pull request).
|
||||||
|
|
|
@ -160,13 +160,13 @@ Toot privacy is handled independently of account privacy, and individually for e
|
||||||
|
|
||||||
**Unlisted** toots are toggled with the "Do not display in public timeline" option in the Compose pane. They are visible to anyone following you and appear on your profile page to the public even without a Mastodon login, but do *not* appear to anyone viewing the Public Timeline while logged into Mastodon.
|
**Unlisted** toots are toggled with the "Do not display in public timeline" option in the Compose pane. They are visible to anyone following you and appear on your profile page to the public even without a Mastodon login, but do *not* appear to anyone viewing the Public Timeline while logged into Mastodon.
|
||||||
|
|
||||||
**Private** toots, finally, are toggled with the "Mark as private" switch. Private toots do not appear in the public timeline nor on your profile page to anyone viewing it unless they are on your Followers list. This means the option is of very limited use if your account is not also set to be private (as anyone can follow you without confirmation and thus see your private toots). However the separation of this means that if you *do* set your entire account to private, you can switch this option off on a toot to make unlisted or even public toots from your otherwise private account.
|
**Private** toots, finally, are toggled with the "Mark as private" switch. Private toots do not appear in the public timeline nor on your profile page to anyone viewing it unless they are on your Followers list. This means the option is of very limited use if your account is not also set to be private (as anyone can follow you without confirmation and thus see your private toots). However the separation of this means that if you *do* set your entire account to private, you can switch this option off on a toot to make unlisted or even public toots from your otherwise private account. Private posts are not encrypted. Make sure you trust your instance admin not to just read your private posts on the back-end.
|
||||||
|
|
||||||
Private toots do not federate to other instances, unless you @mention a remote user. In this case, they will federate to their instance *and may appear there PUBLICLY*. A warning will be displayed if you're composing a private toot that will federate to another instance.
|
Private toots do not federate to other instances, unless you @mention a remote user. In this case, they will federate to their instance *and may appear there PUBLICLY*. A warning will be displayed if you're composing a private toot that will federate to another instance.
|
||||||
|
|
||||||
Private toots cannot be boosted. If someone you follow makes a private toot, it will appear in your timeline with a padlock icon in place of the Boost icon. **NOTE** that remote instances may not respect this.
|
Private toots cannot be boosted. If someone you follow makes a private toot, it will appear in your timeline with a padlock icon in place of the Boost icon. **NOTE** that remote instances may not respect this.
|
||||||
|
|
||||||
**Direct** messages are only visible to users you have @mentioned in them. This does *not* federate to protect your privacy (as other instances may ignore the "Direct" status and display the messages as public if they were to receive them), even if you have @mentioned a remote user.
|
**Direct** posts are only visible to users you have @mentioned in them and cannot be boosted. Like with private posts, you should be mindful that the remote instance may not respect this protocol. If you are discussing a sensitive matter you should move the conversation off of Mastodon.
|
||||||
|
|
||||||
To summarise:
|
To summarise:
|
||||||
|
|
||||||
|
@ -175,7 +175,7 @@ Toot Privacy | Visible on Profile | Visible on Public Timeline | Federates to ot
|
||||||
Public | Anyone incl. anonymous viewers | Yes | Yes
|
Public | Anyone incl. anonymous viewers | Yes | Yes
|
||||||
Unlisted | Anyone incl. anonymous viewers | No | Yes
|
Unlisted | Anyone incl. anonymous viewers | No | Yes
|
||||||
Private | Followers only | No | Only remote @mentions
|
Private | Followers only | No | Only remote @mentions
|
||||||
Direct | No | No | No
|
Direct | No | No | Only remote @mentions
|
||||||
|
|
||||||
#### Blocking
|
#### Blocking
|
||||||
|
|
||||||
|
|
|
@ -310,7 +310,7 @@ Returns a [Status](#status).
|
||||||
|
|
||||||
#### Getting status context:
|
#### Getting status context:
|
||||||
|
|
||||||
GET /api/v1/statuses/:id/contexts
|
GET /api/v1/statuses/:id/context
|
||||||
|
|
||||||
Returns a [Context](#context).
|
Returns a [Context](#context).
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
Fabricator(:account) do
|
Fabricator(:account) do
|
||||||
username "alice"
|
username { Faker::Internet.user_name(nil, %w(_)) }
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
Fabricator(:block) do
|
Fabricator(:block) do
|
||||||
|
account
|
||||||
|
target_account { Fabricate(:account) }
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
Fabricator(:follow) do
|
Fabricator(:follow) do
|
||||||
|
account
|
||||||
|
target_account { Fabricate(:account) }
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
Fabricator(:follow_request) do
|
Fabricator(:follow_request) do
|
||||||
|
account
|
||||||
|
target_account { Fabricate(:account) }
|
||||||
end
|
end
|
||||||
|
|
4
spec/fabricators/mention_fabricator.rb
Normal file
4
spec/fabricators/mention_fabricator.rb
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
Fabricator(:mention) do
|
||||||
|
account
|
||||||
|
status
|
||||||
|
end
|
|
@ -1,6 +1,6 @@
|
||||||
Fabricator(:user) do
|
Fabricator(:user) do
|
||||||
account
|
account
|
||||||
email "alice@example.com"
|
email { Faker::Internet.email }
|
||||||
password "123456789"
|
password "123456789"
|
||||||
confirmed_at { Time.now }
|
confirmed_at { Time.now }
|
||||||
end
|
end
|
||||||
|
|
|
@ -209,4 +209,73 @@ RSpec.describe Account, type: :model do
|
||||||
expect(subject.match('Check this out https://medium.com/@alice/some-article#.abcdef123')).to be_nil
|
expect(subject.match('Check this out https://medium.com/@alice/some-article#.abcdef123')).to be_nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe 'validations' do
|
||||||
|
it 'has a valid fabricator' do
|
||||||
|
account = Fabricate.build(:account)
|
||||||
|
account.valid?
|
||||||
|
expect(account).to be_valid
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'is invalid without a username' do
|
||||||
|
account = Fabricate.build(:account, username: nil)
|
||||||
|
account.valid?
|
||||||
|
expect(account).to model_have_error_on_field(:username)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'is invalid if the username already exists' do
|
||||||
|
account_1 = Fabricate(:account, username: 'the_doctor')
|
||||||
|
account_2 = Fabricate.build(:account, username: 'the_doctor')
|
||||||
|
account_2.valid?
|
||||||
|
expect(account_2).to model_have_error_on_field(:username)
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when is local' do
|
||||||
|
it 'is invalid if the username doesn\'t only contains letters, numbers and underscores' do
|
||||||
|
account = Fabricate.build(:account, username: 'the-doctor')
|
||||||
|
account.valid?
|
||||||
|
expect(account).to model_have_error_on_field(:username)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'is invalid if the username is longer then 30 characters' do
|
||||||
|
account = Fabricate.build(:account, username: Faker::Lorem.characters(31))
|
||||||
|
account.valid?
|
||||||
|
expect(account).to model_have_error_on_field(:username)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'scopes' do
|
||||||
|
describe 'remote' do
|
||||||
|
it 'returns an array of accounts who have a domain' do
|
||||||
|
account_1 = Fabricate(:account, domain: nil)
|
||||||
|
account_2 = Fabricate(:account, domain: 'example.com')
|
||||||
|
expect(Account.remote).to match_array([account_2])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'local' do
|
||||||
|
it 'returns an array of accounts who do not have a domain' do
|
||||||
|
account_1 = Fabricate(:account, domain: nil)
|
||||||
|
account_2 = Fabricate(:account, domain: 'example.com')
|
||||||
|
expect(Account.local).to match_array([account_1])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'silenced' do
|
||||||
|
it 'returns an array of accounts who are silenced' do
|
||||||
|
account_1 = Fabricate(:account, silenced: true)
|
||||||
|
account_2 = Fabricate(:account, silenced: false)
|
||||||
|
expect(Account.silenced).to match_array([account_1])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'suspended' do
|
||||||
|
it 'returns an array of accounts who are suspended' do
|
||||||
|
account_1 = Fabricate(:account, suspended: true)
|
||||||
|
account_2 = Fabricate(:account, suspended: false)
|
||||||
|
expect(Account.suspended).to match_array([account_1])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,5 +1,22 @@
|
||||||
require 'rails_helper'
|
require 'rails_helper'
|
||||||
|
|
||||||
RSpec.describe Block, type: :model do
|
RSpec.describe Block, type: :model do
|
||||||
|
describe 'validations' do
|
||||||
|
it 'has a valid fabricator' do
|
||||||
|
block = Fabricate.build(:block)
|
||||||
|
expect(block).to be_valid
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'is invalid without an account' do
|
||||||
|
block = Fabricate.build(:block, account: nil)
|
||||||
|
block.valid?
|
||||||
|
expect(block).to model_have_error_on_field(:account)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'is invalid without a target_account' do
|
||||||
|
block = Fabricate.build(:block, target_account: nil)
|
||||||
|
block.valid?
|
||||||
|
expect(block).to model_have_error_on_field(:target_account)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,5 +1,23 @@
|
||||||
require 'rails_helper'
|
require 'rails_helper'
|
||||||
|
|
||||||
RSpec.describe DomainBlock, type: :model do
|
RSpec.describe DomainBlock, type: :model do
|
||||||
|
describe 'validations' do
|
||||||
|
it 'has a valid fabricator' do
|
||||||
|
domain_block = Fabricate.build(:domain_block)
|
||||||
|
expect(domain_block).to be_valid
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'is invalid without a domain' do
|
||||||
|
domain_block = Fabricate.build(:domain_block, domain: nil)
|
||||||
|
domain_block.valid?
|
||||||
|
expect(domain_block).to model_have_error_on_field(:domain)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'is invalid if the domain already exists' do
|
||||||
|
domain_block_1 = Fabricate(:domain_block, domain: 'dalek.com')
|
||||||
|
domain_block_2 = Fabricate.build(:domain_block, domain: 'dalek.com')
|
||||||
|
domain_block_2.valid?
|
||||||
|
expect(domain_block_2).to model_have_error_on_field(:domain)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,4 +3,23 @@ require 'rails_helper'
|
||||||
RSpec.describe FollowRequest, type: :model do
|
RSpec.describe FollowRequest, type: :model do
|
||||||
describe '#authorize!'
|
describe '#authorize!'
|
||||||
describe '#reject!'
|
describe '#reject!'
|
||||||
|
|
||||||
|
describe 'validations' do
|
||||||
|
it 'has a valid fabricator' do
|
||||||
|
follow_request = Fabricate.build(:follow_request)
|
||||||
|
expect(follow_request).to be_valid
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'is invalid without an account' do
|
||||||
|
follow_request = Fabricate.build(:follow_request, account: nil)
|
||||||
|
follow_request.valid?
|
||||||
|
expect(follow_request).to model_have_error_on_field(:account)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'is invalid without a target account' do
|
||||||
|
follow_request = Fabricate.build(:follow_request, target_account: nil)
|
||||||
|
follow_request.valid?
|
||||||
|
expect(follow_request).to model_have_error_on_field(:target_account)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -5,4 +5,23 @@ RSpec.describe Follow, type: :model do
|
||||||
let(:bob) { Fabricate(:account, username: 'bob') }
|
let(:bob) { Fabricate(:account, username: 'bob') }
|
||||||
|
|
||||||
subject { Follow.new(account: alice, target_account: bob) }
|
subject { Follow.new(account: alice, target_account: bob) }
|
||||||
|
|
||||||
|
describe 'validations' do
|
||||||
|
it 'has a valid fabricator' do
|
||||||
|
follow = Fabricate.build(:follow)
|
||||||
|
expect(follow).to be_valid
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'is invalid without an account' do
|
||||||
|
follow = Fabricate.build(:follow, account: nil)
|
||||||
|
follow.valid?
|
||||||
|
expect(follow).to model_have_error_on_field(:account)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'is invalid without a target_account' do
|
||||||
|
follow = Fabricate.build(:follow, target_account: nil)
|
||||||
|
follow.valid?
|
||||||
|
expect(follow).to model_have_error_on_field(:target_account)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,5 +1,22 @@
|
||||||
require 'rails_helper'
|
require 'rails_helper'
|
||||||
|
|
||||||
RSpec.describe Mention, type: :model do
|
RSpec.describe Mention, type: :model do
|
||||||
|
describe 'validations' do
|
||||||
|
it 'has a valid fabricator' do
|
||||||
|
mention = Fabricate.build(:mention)
|
||||||
|
expect(mention).to be_valid
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'is invalid without an account' do
|
||||||
|
mention = Fabricate.build(:mention, account: nil)
|
||||||
|
mention.valid?
|
||||||
|
expect(mention).to model_have_error_on_field(:account)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'is invalid without a status' do
|
||||||
|
mention = Fabricate.build(:mention, status: nil)
|
||||||
|
mention.valid?
|
||||||
|
expect(mention).to model_have_error_on_field(:status)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,5 +1,88 @@
|
||||||
require 'rails_helper'
|
require 'rails_helper'
|
||||||
|
|
||||||
RSpec.describe User, type: :model do
|
RSpec.describe User, type: :model do
|
||||||
|
describe 'validations' do
|
||||||
|
it 'is invalid without an account' do
|
||||||
|
user = Fabricate.build(:user, account: nil)
|
||||||
|
user.valid?
|
||||||
|
expect(user).to model_have_error_on_field(:account)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'is invalid without a valid locale' do
|
||||||
|
user = Fabricate.build(:user, locale: 'toto')
|
||||||
|
user.valid?
|
||||||
|
expect(user).to model_have_error_on_field(:locale)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'is invalid without a valid email' do
|
||||||
|
user = Fabricate.build(:user, email: 'john@')
|
||||||
|
user.valid?
|
||||||
|
expect(user).to model_have_error_on_field(:email)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'scopes' do
|
||||||
|
describe 'recent' do
|
||||||
|
it 'returns an array of recent users ordered by id' do
|
||||||
|
user_1 = Fabricate(:user)
|
||||||
|
user_2 = Fabricate(:user)
|
||||||
|
expect(User.recent).to match_array([user_2, user_1])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'admins' do
|
||||||
|
it 'returns an array of users who are admin' do
|
||||||
|
user_1 = Fabricate(:user, admin: false)
|
||||||
|
user_2 = Fabricate(:user, admin: true)
|
||||||
|
expect(User.admins).to match_array([user_2])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'confirmed' do
|
||||||
|
it 'returns an array of users who are confirmed' do
|
||||||
|
user_1 = Fabricate(:user, confirmed_at: nil)
|
||||||
|
user_2 = Fabricate(:user, confirmed_at: Time.now)
|
||||||
|
expect(User.confirmed).to match_array([user_2])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
let(:account) { Fabricate(:account, username: 'alice') }
|
||||||
|
let(:password) { 'abcd1234' }
|
||||||
|
|
||||||
|
describe 'blacklist' do
|
||||||
|
it 'should allow a non-blacklisted user to be created' do
|
||||||
|
user = User.new(email: 'foo@example.com', account: account, password: password)
|
||||||
|
|
||||||
|
expect(user.valid?).to be_truthy
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'should not allow a blacklisted user to be created' do
|
||||||
|
user = User.new(email: 'foo@mvrht.com', account: account, password: password)
|
||||||
|
|
||||||
|
expect(user.valid?).to be_falsey
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'whitelist' do
|
||||||
|
around(:each) do |example|
|
||||||
|
old_whitelist = Rails.configuration.x.email_whitelist
|
||||||
|
|
||||||
|
Rails.configuration.x.email_domains_whitelist = 'mastodon.space'
|
||||||
|
|
||||||
|
example.run
|
||||||
|
|
||||||
|
Rails.configuration.x.email_domains_whitelist = old_whitelist
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'should not allow a user to be created unless they are whitelisted' do
|
||||||
|
user = User.new(email: 'foo@example.com', account: account, password: password)
|
||||||
|
expect(user.valid?).to be_falsey
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'should allow a user to be created if they are whitelisted' do
|
||||||
|
user = User.new(email: 'foo@mastodon.space', account: account, password: password)
|
||||||
|
expect(user.valid?).to be_truthy
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -8,6 +8,8 @@ require 'rspec/rails'
|
||||||
require 'webmock/rspec'
|
require 'webmock/rspec'
|
||||||
require 'paperclip/matchers'
|
require 'paperclip/matchers'
|
||||||
|
|
||||||
|
Dir[Rails.root.join('spec/support/**/*.rb')].each { |f| require f }
|
||||||
|
|
||||||
ActiveRecord::Migration.maintain_test_schema!
|
ActiveRecord::Migration.maintain_test_schema!
|
||||||
WebMock.disable_net_connect!(allow: 'localhost:7575')
|
WebMock.disable_net_connect!(allow: 'localhost:7575')
|
||||||
Sidekiq::Testing.inline!
|
Sidekiq::Testing.inline!
|
||||||
|
|
15
spec/support/matchers/model/model_have_error_on_field.rb
Normal file
15
spec/support/matchers/model/model_have_error_on_field.rb
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
RSpec::Matchers.define :model_have_error_on_field do |expected|
|
||||||
|
match do |record|
|
||||||
|
if record.errors.empty?
|
||||||
|
record.valid?
|
||||||
|
end
|
||||||
|
|
||||||
|
record.errors.has_key?(expected)
|
||||||
|
end
|
||||||
|
|
||||||
|
failure_message do |record|
|
||||||
|
keys = record.errors.keys
|
||||||
|
|
||||||
|
"expect record.errors(#{keys}) to include #{expected}"
|
||||||
|
end
|
||||||
|
end
|
Reference in a new issue