Merge branch 'master' into patch-1
This commit is contained in:
commit
cb1617245b
23 changed files with 158 additions and 78 deletions
|
@ -22,6 +22,8 @@ OTP_SECRET=
|
|||
# SINGLE_USER_MODE=true
|
||||
# Prevent registrations with following e-mail domains
|
||||
# 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
|
||||
SMTP_SERVER=smtp.mailgun.org
|
||||
|
|
|
@ -22,10 +22,10 @@ const fi = {
|
|||
"account.followers": "Seuraajia",
|
||||
"account.follows_you": "Seuraa sinua",
|
||||
"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_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.community": "Paikallinen aikajana",
|
||||
"column.public": "Yhdistetty aikajana",
|
||||
|
|
|
@ -8,6 +8,7 @@ class RemoteFollowController < ApplicationController
|
|||
|
||||
def new
|
||||
@remote_follow = RemoteFollow.new
|
||||
@remote_follow.acct = session[:remote_follow] if session.key?(:remote_follow)
|
||||
end
|
||||
|
||||
def create
|
||||
|
@ -22,6 +23,8 @@ class RemoteFollowController < ApplicationController
|
|||
render(:new) && return
|
||||
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
|
||||
else
|
||||
render :new
|
||||
|
|
|
@ -2,17 +2,30 @@
|
|||
|
||||
class EmailValidator < ActiveModel::EachValidator
|
||||
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)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
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('.', '\.')
|
||||
regexp = Regexp.new("@(.+\\.)?(#{domains})", true)
|
||||
|
||||
value =~ regexp
|
||||
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
|
||||
|
|
|
@ -11,11 +11,11 @@ class FeedManager
|
|||
"feed:#{type}:#{id}"
|
||||
end
|
||||
|
||||
def filter?(timeline_type, status, receiver)
|
||||
def filter?(timeline_type, status, receiver_id)
|
||||
if timeline_type == :home
|
||||
filter_from_home?(status, receiver)
|
||||
filter_from_home?(status, receiver_id)
|
||||
elsif timeline_type == :mentions
|
||||
filter_from_mentions?(status, receiver)
|
||||
filter_from_mentions?(status, receiver_id)
|
||||
else
|
||||
false
|
||||
end
|
||||
|
@ -91,39 +91,39 @@ class FeedManager
|
|||
Redis.current
|
||||
end
|
||||
|
||||
def filter_from_home?(status, receiver)
|
||||
def filter_from_home?(status, receiver_id)
|
||||
return true if status.reply? && status.in_reply_to_id.nil?
|
||||
|
||||
check_for_mutes = [status.account_id]
|
||||
check_for_mutes.concat([status.reblog.account_id]) if status.reblog?
|
||||
|
||||
return true if receiver.muting?(check_for_mutes)
|
||||
return true if Mute.where(account_id: receiver_id, target_account_id: check_for_mutes).any?
|
||||
|
||||
check_for_blocks = status.mentions.map(&:account_id)
|
||||
check_for_blocks.concat([status.reblog.account_id]) if status.reblog?
|
||||
|
||||
return true if receiver.blocking?(check_for_blocks)
|
||||
return true if Block.where(account_id: receiver_id, target_account_id: check_for_blocks).any?
|
||||
|
||||
if status.reply? && !status.in_reply_to_account_id.nil? # Filter out if it's a reply
|
||||
should_filter = !receiver.following?(status.in_reply_to_account) # and I'm not following the person it's a reply to
|
||||
should_filter &&= !(receiver.id == status.in_reply_to_account_id) # and it's not a reply to me
|
||||
should_filter &&= !(status.account_id == status.in_reply_to_account_id) # and it's not a self-reply
|
||||
if status.reply? && !status.in_reply_to_account_id.nil? # Filter out if it's a reply
|
||||
should_filter = !Follow.where(account_id: receiver_id, target_account_id: status.in_reply_to_account_id).exists? # and I'm not following the person it's a reply to
|
||||
should_filter &&= !(receiver_id == status.in_reply_to_account_id) # and it's not a reply to me
|
||||
should_filter &&= !(status.account_id == status.in_reply_to_account_id) # and it's not a self-reply
|
||||
return should_filter
|
||||
elsif status.reblog? # Filter out a reblog
|
||||
return status.reblog.account.blocking?(receiver) # or if the author of the reblogged status is blocking me
|
||||
elsif status.reblog? # Filter out a reblog
|
||||
return Block.where(account_id: status.reblog.account_id, target_account_id: receiver_id).exists? # or if the author of the reblogged status is blocking me
|
||||
end
|
||||
|
||||
false
|
||||
end
|
||||
|
||||
def filter_from_mentions?(status, receiver)
|
||||
def filter_from_mentions?(status, receiver_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?
|
||||
|
||||
should_filter = receiver.id == status.account_id # Filter if I'm mentioning myself
|
||||
should_filter ||= receiver.blocking?(check_for_blocks) # or it's from someone I blocked, in reply to someone I blocked, or mentioning someone I blocked
|
||||
should_filter ||= (status.account.silenced? && !receiver.following?(status.account)) # of if the account is silenced and I'm not following them
|
||||
should_filter = receiver_id == status.account_id # Filter if I'm mentioning myself
|
||||
should_filter ||= Block.where(account_id: receiver_id, target_account_id: check_for_blocks).any? # or it's from someone I blocked, in reply to someone I blocked, or mentioning someone I blocked
|
||||
should_filter ||= (status.account.silenced? && !Follow.where(account_id: receiver_id, target_account_id: status.account_id).exists?) # of if the account is silenced and I'm not following them
|
||||
|
||||
should_filter
|
||||
end
|
||||
|
|
|
@ -33,9 +33,8 @@ class FanOutOnWriteService < BaseService
|
|||
def deliver_to_followers(status)
|
||||
Rails.logger.debug "Delivering status #{status.id} to followers"
|
||||
|
||||
status.account.followers.where(domain: nil).joins(:user).where('users.current_sign_in_at > ?', 14.days.ago).find_each do |follower|
|
||||
next if FeedManager.instance.filter?(:home, status, follower)
|
||||
FeedManager.instance.push(:home, follower, status)
|
||||
status.account.followers.where(domain: nil).joins(:user).where('users.current_sign_in_at > ?', 14.days.ago).select(:id).find_each do |follower|
|
||||
FeedInsertWorker.perform_async(status.id, follower.id)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -44,7 +43,7 @@ class FanOutOnWriteService < BaseService
|
|||
|
||||
status.mentions.includes(:account).each do |mention|
|
||||
mentioned_account = mention.account
|
||||
next if !mentioned_account.local? || !mentioned_account.following?(status.account) || FeedManager.instance.filter?(:home, status, mentioned_account)
|
||||
next if !mentioned_account.local? || !mentioned_account.following?(status.account) || FeedManager.instance.filter?(:home, status, mention.account_id)
|
||||
FeedManager.instance.push(:home, mentioned_account, status)
|
||||
end
|
||||
end
|
||||
|
@ -54,9 +53,9 @@ class FanOutOnWriteService < BaseService
|
|||
|
||||
payload = FeedManager.instance.inline_render(nil, 'api/v1/statuses/show', status)
|
||||
|
||||
status.tags.find_each do |tag|
|
||||
FeedManager.instance.broadcast("hashtag:#{tag.name}", event: 'update', payload: payload)
|
||||
FeedManager.instance.broadcast("hashtag:#{tag.name}:local", event: 'update', payload: payload) if status.account.local?
|
||||
status.tags.pluck(:name).each do |hashtag|
|
||||
FeedManager.instance.broadcast("hashtag:#{hashtag}", event: 'update', payload: payload)
|
||||
FeedManager.instance.broadcast("hashtag:#{hashtag}:local", event: 'update', payload: payload) if status.account.local?
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ class NotifyService < BaseService
|
|||
private
|
||||
|
||||
def blocked_mention?
|
||||
FeedManager.instance.filter?(:mentions, @notification.mention.status, @recipient)
|
||||
FeedManager.instance.filter?(:mentions, @notification.mention.status, @recipient.id)
|
||||
end
|
||||
|
||||
def blocked_favourite?
|
||||
|
|
|
@ -7,7 +7,7 @@ class PrecomputeFeedService < BaseService
|
|||
def call(_, account)
|
||||
redis.pipelined do
|
||||
Status.as_home_timeline(account).limit(FeedManager::MAX_ITEMS / 4).each do |status|
|
||||
next if status.direct_visibility? || FeedManager.instance.filter?(:home, status, account)
|
||||
next if status.direct_visibility? || FeedManager.instance.filter?(:home, status, account.id)
|
||||
redis.zadd(FeedManager.instance.key(:home, account.id), status.id, status.reblog? ? status.reblog_of_id : status.id)
|
||||
end
|
||||
end
|
||||
|
|
15
app/workers/feed_insert_worker.rb
Normal file
15
app/workers/feed_insert_worker.rb
Normal file
|
@ -0,0 +1,15 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class FeedInsertWorker
|
||||
include Sidekiq::Worker
|
||||
|
||||
def perform(status_id, follower_id)
|
||||
status = Status.find(status_id)
|
||||
follower = Account.find(follower_id)
|
||||
|
||||
return if FeedManager.instance.filter?(:home, status, follower.id)
|
||||
FeedManager.instance.push(:home, follower, status)
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
true
|
||||
end
|
||||
end
|
|
@ -22,6 +22,7 @@ class Pubsubhubbub::DeliveryWorker
|
|||
.headers(headers)
|
||||
.post(subscription.callback_url, body: payload)
|
||||
|
||||
return subscription.destroy! if response.code > 299 && response.code < 500 && response.code != 429 # HTTP 4xx means error is not temporary, except for 429 (throttling)
|
||||
raise "Delivery failed for #{subscription.callback_url}: HTTP #{response.code}" unless response.code > 199 && response.code < 300
|
||||
|
||||
subscription.touch(:last_successful_delivery_at)
|
||||
|
|
|
@ -2,4 +2,5 @@
|
|||
|
||||
Rails.application.configure do
|
||||
config.x.email_domains_blacklist = ENV.fetch('EMAIL_DOMAIN_BLACKLIST') { 'mvrht.com' }
|
||||
config.x.email_domains_whitelist = ENV.fetch('EMAIL_DOMAIN_WHITELIST') { '' }
|
||||
end
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
---
|
||||
de:
|
||||
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
|
||||
source_code: Quellcode
|
||||
terms: AGB
|
||||
accounts:
|
||||
follow: Folgen
|
||||
followers: Folger
|
||||
following: Folgt
|
||||
followers: Follower
|
||||
following: Gefolgt
|
||||
nothing_here: Hier gibt es nichts!
|
||||
people_followed_by: Nutzer, denen %{name} folgt
|
||||
people_who_follow: Nutzer, die %{name} folgen
|
||||
|
@ -27,7 +27,7 @@ de:
|
|||
reset_password: Passwort zurücksetzen
|
||||
set_new_password: Neues Passwort setzen
|
||||
authorize_follow:
|
||||
error: Das entfernte Profil konnte nicht geladen werden
|
||||
error: Das Profil konnte nicht geladen werden
|
||||
follow: Folgen
|
||||
prompt_html: 'Du (<strong>%{self}</strong>) möchtest dieser Person folgen:'
|
||||
title: "%{acct} folgen"
|
||||
|
@ -55,25 +55,25 @@ de:
|
|||
notification_mailer:
|
||||
favourite:
|
||||
body: 'Dein Beitrag wurde von %{name} favorisiert:'
|
||||
subject: "%{name} hat deinen Beitrag favorisiert"
|
||||
subject: "%{name} hat deinen Beitrag favorisiert."
|
||||
follow:
|
||||
body: "%{name} folgt dir jetzt!"
|
||||
subject: "%{name} folgt dir nun"
|
||||
subject: "%{name} folgt dir jetzt."
|
||||
follow_request:
|
||||
body: "%{name} möchte dir folgen:"
|
||||
subject: "%{name} möchte dir folgen"
|
||||
subject: "%{name} möchte dir folgen."
|
||||
mention:
|
||||
body: "%{name} hat dich erwähnt:"
|
||||
subject: "%{name} hat dich erwähnt"
|
||||
subject: "%{name} hat dich erwähnt."
|
||||
reblog:
|
||||
body: 'Dein Beitrag wurde von %{name} geteilt:'
|
||||
subject: "%{name} teilte deinen Beitrag"
|
||||
subject: "%{name} teilte deinen Beitrag."
|
||||
pagination:
|
||||
next: Vorwärts
|
||||
prev: Zurück
|
||||
remote_follow:
|
||||
acct: Dein Nutzername@Domain, von dem du dieser Person folgen möchtest
|
||||
missing_resource: Die erforderliche Weiterleitungs-URL konnte leider in deinem Profil nicht gefunden werden
|
||||
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.
|
||||
proceed: Weiter
|
||||
prompt: 'Du wirst dieser Person folgen:'
|
||||
settings:
|
||||
|
|
|
@ -2,59 +2,59 @@
|
|||
de:
|
||||
devise:
|
||||
confirmations:
|
||||
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_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."
|
||||
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_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:
|
||||
already_authenticated: "Du bist bereits angemeldet."
|
||||
inactive: "Dein Account ist nicht aktiv."
|
||||
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."
|
||||
not_found_in_database: "E-Mail-Adresse oder Passwort ungültig."
|
||||
timeout: "Deine Sitzung ist abgelaufen, bitte melde Dich erneut an."
|
||||
unauthenticated: "Du musst Dich anmelden oder registrieren, bevor Du fortfahren kannst."
|
||||
unconfirmed: "Du musst Deinen Account bestätigen, bevor Du fortfahren kannst."
|
||||
timeout: "Deine Sitzung ist abgelaufen, bitte melde dich erneut an."
|
||||
unauthenticated: "Du musst Dich anmelden oder registrieren, bevor du fortfahren kannst."
|
||||
unconfirmed: "Du musst deinen Account bestätigen, bevor du fortfahren kannst."
|
||||
mailer:
|
||||
confirmation_instructions:
|
||||
subject: "Mastodon: Anleitung zur Bestätigung Deines Accounts"
|
||||
subject: "Mastodon: Anleitung zur Bestätigung deines Accounts"
|
||||
password_change:
|
||||
subject: 'Mastodon: Passwort wurde geändert'
|
||||
reset_password_instructions:
|
||||
subject: "Mastodon: Anleitung um Dein Passwort zurückzusetzen"
|
||||
subject: "Mastodon: Anleitung um dein Passwort zurückzusetzen"
|
||||
unlock_instructions:
|
||||
subject: "Mastodon: Anleitung um Deinen Account freizuschalten"
|
||||
subject: "Mastodon: Anleitung um deinen Account freizuschalten"
|
||||
omniauth_callbacks:
|
||||
failure: "Du konntest nicht Deinem %{kind}-Account angemeldet werden, weil '%{reason}'."
|
||||
success: "Du hast Dich erfolgreich mit Deinem %{kind}-Account angemeldet."
|
||||
failure: "Du konntest nicht mit deinem %{kind}-Account angemeldet werden, weil '%{reason}'."
|
||||
success: "Du hast dich erfolgreich mit Deinem %{kind}-Account angemeldet."
|
||||
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."
|
||||
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."
|
||||
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_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_not_active: "Dein Passwort wurde geändert."
|
||||
registrations:
|
||||
destroyed: "Dein Account wurde gelöscht."
|
||||
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_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."
|
||||
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."
|
||||
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_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."
|
||||
updated: "Deine Daten wurden aktualisiert."
|
||||
sessions:
|
||||
already_signed_out: "Erfolgreich abgemeldet."
|
||||
signed_in: "Erfolgreich angemeldet."
|
||||
signed_out: "Erfolgreich abgemeldet."
|
||||
unlocks:
|
||||
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_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."
|
||||
unlocked: "Dein Account wurde entsperrt. Du bist jetzt angemeldet."
|
||||
errors:
|
||||
messages:
|
||||
already_confirmed: "wurde bereits bestätigt"
|
||||
confirmation_period_expired: "muss innerhalb %{period} bestätigt werden, bitte fordere einen neuen Link an"
|
||||
expired: "ist abgelaufen, bitte neu anfordern"
|
||||
not_found: "nicht gefunden"
|
||||
already_confirmed: "wurde bereits bestätigt."
|
||||
confirmation_period_expired: "muss innerhalb %{period} bestätigt werden, bitte fordere einen neuen Link an."
|
||||
expired: "ist abgelaufen, bitte neu anfordern."
|
||||
not_found: "wurde nicht gefunden."
|
||||
not_locked: "ist nicht gesperrt"
|
||||
not_saved:
|
||||
one: "Konnte %{resource} nicht speichern: ein Fehler."
|
||||
|
|
|
@ -62,7 +62,7 @@ fr:
|
|||
buttons:
|
||||
revoke: Annuler
|
||||
confirmations:
|
||||
revoke: Êtes-vous certain?
|
||||
revoke: Êtes-vous certain ?
|
||||
index:
|
||||
application: Application
|
||||
created_at: Créé le
|
||||
|
@ -72,19 +72,19 @@ fr:
|
|||
errors:
|
||||
messages:
|
||||
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_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_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_token:
|
||||
expired: Le jeton d'accès a expiré
|
||||
revoked: Le jeton d'accès a été révoqué
|
||||
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é.
|
||||
server_error: Le serveur d'autorisation a rencontré une condition inattendue qui l'a empêché de remplir la demande.
|
||||
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 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.
|
||||
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.
|
||||
|
|
|
@ -5,6 +5,7 @@ fr:
|
|||
about_this: À propos de cette instance
|
||||
apps: Applications
|
||||
business_email: E-mail professionnel
|
||||
closed_registrations: Les inscriptions sont actuellement fermées sur cette instance. .
|
||||
description_headline: Qu'est-ce que %{domain} ?
|
||||
domain_count_after: autres instances
|
||||
domain_count_before: Connectés à
|
||||
|
|
|
@ -38,7 +38,7 @@ en:
|
|||
follow: Send e-mail when someone follows you
|
||||
follow_request: Send e-mail when someone requests to follow 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'
|
||||
required:
|
||||
mark: "*"
|
||||
|
|
|
@ -6,7 +6,7 @@ fi:
|
|||
avatar: PNG, GIF tai JPG. Korkeintaan 2MB. Skaalataan kokoon 120x120px
|
||||
display_name: Korkeintaan 30 merkkiä
|
||||
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ä
|
||||
imports:
|
||||
data: CSV tiedosto tuotu toiselta Mastodon palvelimelta
|
||||
|
|
|
@ -7,7 +7,7 @@ So, you have a working Mastodon instance... now what?
|
|||
|
||||
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.
|
||||
|
||||
|
|
|
@ -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.
|
||||
* 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.
|
||||
|
||||
You may need to use the `heroku` CLI application to run `USERNAME=yourUsername rails mastodon:make_admin` to make yourself an admin.
|
||||
|
|
|
@ -76,7 +76,7 @@ It is recommended to create a special user for mastodon on the server (you could
|
|||
## General dependencies
|
||||
|
||||
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
|
||||
|
||||
## Redis
|
||||
|
@ -132,7 +132,7 @@ Fill in the important data, like host/port of the redis database, host/port/user
|
|||
|
||||
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
|
||||
|
||||
|
@ -221,7 +221,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 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
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ There is also a list at [instances.mastodon.xyz](https://instances.mastodon.xyz)
|
|||
| [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|
|
||||
| [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|
|
||||
| [mastodon.xyz](https://mastodon.xyz) |N/A|Yes|Yes|
|
||||
| [social.targaryen.house](https://social.targaryen.house) |Federates everywhere, quick updates.|Yes|Yes|
|
||||
|
@ -22,8 +22,10 @@ There is also a list at [instances.mastodon.xyz](https://instances.mastodon.xyz)
|
|||
| [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|
|
||||
| [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|
|
||||
| [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|
|
||||
| [social.lou.lt](https://social.lou.lt) |N/A|Yes|No|
|
||||
| [mastodon.ninetailed.uk](https://mastodon.ninetailed.uk) |N/A|Yes|No|
|
||||
|
@ -35,5 +37,8 @@ There is also a list at [instances.mastodon.xyz](https://instances.mastodon.xyz)
|
|||
| [social.lkw.tf](https://social.lkw.tf)|N/A|No|No|
|
||||
| [manowar.social](https://manowar.social)|N/A|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|
|
||||
|
||||
Let me know if you start running one so I can add it to the list! (Alternatively, add it yourself as a pull request).
|
||||
|
|
|
@ -1,5 +1,42 @@
|
|||
require 'rails_helper'
|
||||
|
||||
RSpec.describe User, type: :model do
|
||||
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
|
||||
|
|
|
@ -23,6 +23,7 @@ RSpec.describe FanOutOnWriteService do
|
|||
end
|
||||
|
||||
it 'delivers status to local followers' do
|
||||
pending 'some sort of problem in test environment causes this to sometimes fail'
|
||||
expect(Feed.new(:home, follower).get(10).map(&:id)).to include status.id
|
||||
end
|
||||
|
||||
|
|
Loading…
Reference in a new issue