Merge remote-tracking branch 'tootsuite/master' into glitchsoc/master
This commit is contained in:
		
						commit
						c69a23ae46
					
				|  | @ -299,13 +299,11 @@ GEM | |||
|       sidekiq (>= 3.5.0) | ||||
|       statsd-ruby (~> 1.2.0) | ||||
|     oj (3.3.9) | ||||
|     openssl (2.0.6) | ||||
|     orm_adapter (0.5.0) | ||||
|     ostatus2 (2.0.1) | ||||
|     ostatus2 (2.0.2) | ||||
|       addressable (~> 2.4) | ||||
|       http (~> 2.0) | ||||
|       nokogiri (~> 1.6) | ||||
|       openssl (~> 2.0) | ||||
|     ox (2.8.2) | ||||
|     paperclip (5.1.0) | ||||
|       activemodel (>= 4.2.0) | ||||
|  |  | |||
|  | @ -2,7 +2,8 @@ | |||
| 
 | ||||
| class AccountsController < ApplicationController | ||||
|   include AccountControllerConcern | ||||
|   include SignatureVerification | ||||
| 
 | ||||
|   before_action :set_cache_headers | ||||
| 
 | ||||
|   def show | ||||
|     respond_to do |format| | ||||
|  | @ -27,10 +28,11 @@ class AccountsController < ApplicationController | |||
|       end | ||||
| 
 | ||||
|       format.json do | ||||
|         render json: @account, | ||||
|                serializer: ActivityPub::ActorSerializer, | ||||
|                adapter: ActivityPub::Adapter, | ||||
|                content_type: 'application/activity+json' | ||||
|         skip_session! | ||||
| 
 | ||||
|         render_cached_json(['activitypub', 'actor', @account.cache_key], content_type: 'application/activity+json') do | ||||
|           ActiveModelSerializers::SerializableResource.new(@account, serializer: ActivityPub::ActorSerializer, adapter: ActivityPub::Adapter) | ||||
|         end | ||||
|       end | ||||
|     end | ||||
|   end | ||||
|  |  | |||
|  | @ -4,15 +4,19 @@ class ActivityPub::FollowsController < Api::BaseController | |||
|   include SignatureVerification | ||||
| 
 | ||||
|   def show | ||||
|     render( | ||||
|       json: FollowRequest.includes(:account).references(:account).find_by!( | ||||
|         id: params.require(:id), | ||||
|         accounts: { domain: nil, username: params.require(:account_username) }, | ||||
|         target_account: signed_request_account | ||||
|       ), | ||||
|       serializer: ActivityPub::FollowSerializer, | ||||
|       adapter: ActivityPub::Adapter, | ||||
|       content_type: 'application/activity+json' | ||||
|     render json: follow_request, | ||||
|            serializer: ActivityPub::FollowSerializer, | ||||
|            adapter: ActivityPub::Adapter, | ||||
|            content_type: 'application/activity+json' | ||||
|   end | ||||
| 
 | ||||
|   private | ||||
| 
 | ||||
|   def follow_request | ||||
|     FollowRequest.includes(:account).references(:account).find_by!( | ||||
|       id: params.require(:id), | ||||
|       accounts: { domain: nil, username: params.require(:account_username) }, | ||||
|       target_account: signed_request_account | ||||
|     ) | ||||
|   end | ||||
| end | ||||
|  |  | |||
|  | @ -198,11 +198,24 @@ class ApplicationController < ActionController::Base | |||
|   end | ||||
| 
 | ||||
|   def render_cached_json(cache_key, **options) | ||||
|     options[:expires_in] ||= 3.minutes | ||||
|     options[:public]     ||= true | ||||
|     cache_key              = cache_key.join(':') if cache_key.is_a?(Enumerable) | ||||
|     content_type           = options.delete(:content_type) || 'application/json' | ||||
| 
 | ||||
|     data = Rails.cache.fetch(cache_key, { raw: true }.merge(options)) do | ||||
|       yield.to_json | ||||
|     end | ||||
| 
 | ||||
|     expires_in options[:expires_in], public: true | ||||
|     render json: data | ||||
|     expires_in options[:expires_in], public: options[:public] | ||||
|     render json: data, content_type: content_type | ||||
|   end | ||||
| 
 | ||||
|   def set_cache_headers | ||||
|     response.headers['Vary'] = 'Accept' | ||||
|   end | ||||
| 
 | ||||
|   def skip_session! | ||||
|     request.session_options[:skip] = true | ||||
|   end | ||||
| end | ||||
|  |  | |||
|  | @ -2,14 +2,16 @@ | |||
| 
 | ||||
| class EmojisController < ApplicationController | ||||
|   before_action :set_emoji | ||||
|   before_action :set_cache_headers | ||||
| 
 | ||||
|   def show | ||||
|     respond_to do |format| | ||||
|       format.json do | ||||
|         render json: @emoji, | ||||
|                serializer: ActivityPub::EmojiSerializer, | ||||
|                adapter: ActivityPub::Adapter, | ||||
|                content_type: 'application/activity+json' | ||||
|         skip_session! | ||||
| 
 | ||||
|         render_cached_json(['activitypub', 'emoji', @emoji.cache_key], content_type: 'application/activity+json') do | ||||
|           ActiveModelSerializers::SerializableResource.new(@emoji, serializer: ActivityPub::EmojiSerializer, adapter: ActivityPub::Adapter) | ||||
|         end | ||||
|       end | ||||
|     end | ||||
|   end | ||||
|  |  | |||
|  | @ -10,7 +10,7 @@ class StatusesController < ApplicationController | |||
|   before_action :set_link_headers | ||||
|   before_action :check_account_suspension | ||||
|   before_action :redirect_to_original, only: [:show] | ||||
|   before_action { response.headers['Vary'] = 'Accept' } | ||||
|   before_action :set_cache_headers | ||||
| 
 | ||||
|   def show | ||||
|     respond_to do |format| | ||||
|  | @ -23,25 +23,21 @@ class StatusesController < ApplicationController | |||
|       end | ||||
| 
 | ||||
|       format.json do | ||||
|         render json: @status, | ||||
|                serializer: ActivityPub::NoteSerializer, | ||||
|                adapter: ActivityPub::Adapter, | ||||
|                content_type: 'application/activity+json' | ||||
|         skip_session! unless @stream_entry.hidden? | ||||
| 
 | ||||
|         # Allow HTTP caching for 3 minutes if the status is public | ||||
|         unless @stream_entry.hidden? | ||||
|           request.session_options[:skip] = true | ||||
|           expires_in(3.minutes, public: true) | ||||
|         render_cached_json(['activitypub', 'note', @status.cache_key], content_type: 'application/activity+json', public: !@stream_entry.hidden?) do | ||||
|           ActiveModelSerializers::SerializableResource.new(@status, serializer: ActivityPub::NoteSerializer, adapter: ActivityPub::Adapter) | ||||
|         end | ||||
|       end | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
|   def activity | ||||
|     render json: @status, | ||||
|            serializer: ActivityPub::ActivitySerializer, | ||||
|            adapter: ActivityPub::Adapter, | ||||
|            content_type: 'application/activity+json' | ||||
|     skip_session! | ||||
| 
 | ||||
|     render_cached_json(['activitypub', 'activity', @status.cache_key], content_type: 'application/activity+json', public: !@stream_entry.hidden?) do | ||||
|       ActiveModelSerializers::SerializableResource.new(@status, serializer: ActivityPub::ActivitySerializer, adapter: ActivityPub::Adapter) | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
|   def embed | ||||
|  |  | |||
|  | @ -34,7 +34,7 @@ module Admin::ActionLogsHelper | |||
|       link_to attributes['domain'], "https://#{attributes['domain']}" | ||||
|     when 'Status' | ||||
|       tmp_status = Status.new(attributes) | ||||
|       link_to tmp_status.account.acct, TagManager.instance.url_for(tmp_status) | ||||
|       link_to tmp_status.account&.acct || "##{tmp_status.account_id}", TagManager.instance.url_for(tmp_status) | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
|  |  | |||
|  | @ -4,6 +4,7 @@ module RoutingHelper | |||
|   extend ActiveSupport::Concern | ||||
|   include Rails.application.routes.url_helpers | ||||
|   include ActionView::Helpers::AssetTagHelper | ||||
|   include Webpacker::Helper | ||||
| 
 | ||||
|   included do | ||||
|     def default_url_options | ||||
|  | @ -17,6 +18,10 @@ module RoutingHelper | |||
|     URI.join(root_url, source).to_s | ||||
|   end | ||||
| 
 | ||||
|   def full_pack_url(source, **options) | ||||
|     full_asset_url(asset_pack_path(source, options)) | ||||
|   end | ||||
| 
 | ||||
|   private | ||||
| 
 | ||||
|   def use_storage? | ||||
|  |  | |||
|  | @ -70,30 +70,28 @@ export default class GettingStarted extends ImmutablePureComponent { | |||
| 
 | ||||
|     navItems.push( | ||||
|       <ColumnLink key='4' icon='star' text={intl.formatMessage(messages.favourites)} to='/favourites' />, | ||||
|       <ColumnLink key='5' icon='thumb-tack' text={intl.formatMessage(messages.pins)} to='/pinned' />, | ||||
|       <ColumnLink key='6' icon='bars' text={intl.formatMessage(messages.lists)} to='/lists' /> | ||||
|       <ColumnLink key='5' icon='bars' text={intl.formatMessage(messages.lists)} to='/lists' /> | ||||
|     ); | ||||
| 
 | ||||
|     if (myAccount.get('locked')) { | ||||
|       navItems.push(<ColumnLink key='7' icon='users' text={intl.formatMessage(messages.follow_requests)} to='/follow_requests' />); | ||||
|       navItems.push(<ColumnLink key='6' icon='users' text={intl.formatMessage(messages.follow_requests)} to='/follow_requests' />); | ||||
|     } | ||||
| 
 | ||||
|     navItems.push( | ||||
|       <ColumnLink key='8' icon='volume-off' text={intl.formatMessage(messages.mutes)} to='/mutes' />, | ||||
|       <ColumnLink key='9' icon='ban' text={intl.formatMessage(messages.blocks)} to='/blocks' /> | ||||
|     ); | ||||
| 
 | ||||
|     if (multiColumn) { | ||||
|       navItems.push(<ColumnLink key='10' icon='question' text={intl.formatMessage(messages.keyboard_shortcuts)} to='/keyboard-shortcuts' />); | ||||
|       navItems.push(<ColumnLink key='7' icon='question' text={intl.formatMessage(messages.keyboard_shortcuts)} to='/keyboard-shortcuts' />); | ||||
|     } | ||||
| 
 | ||||
|     navItems.push(<ColumnLink key='8' icon='book' text={intl.formatMessage(messages.info)} href='/about/more' />); | ||||
| 
 | ||||
|     return ( | ||||
|       <Column icon='asterisk' heading={intl.formatMessage(messages.heading)} hideHeadingOnMobile> | ||||
|         <div className='getting-started__wrapper'> | ||||
|           <ColumnSubheading text={intl.formatMessage(messages.navigation_subheading)} /> | ||||
|           {navItems} | ||||
|           <ColumnSubheading text={intl.formatMessage(messages.settings_subheading)} /> | ||||
|           <ColumnLink icon='book' text={intl.formatMessage(messages.info)} href='/about/more' /> | ||||
|           <ColumnLink icon='thumb-tack' text={intl.formatMessage(messages.pins)} to='/pinned' /> | ||||
|           <ColumnLink icon='volume-off' text={intl.formatMessage(messages.mutes)} to='/mutes' /> | ||||
|           <ColumnLink icon='ban' text={intl.formatMessage(messages.blocks)} to='/blocks' /> | ||||
|           <ColumnLink icon='cog' text={intl.formatMessage(messages.preferences)} href='/settings/preferences' /> | ||||
|           <ColumnLink icon='sign-out' text={intl.formatMessage(messages.sign_out)} href='/auth/sign_out' method='delete' /> | ||||
|         </div> | ||||
|  |  | |||
|  | @ -11,7 +11,7 @@ | |||
|   "account.media": "Mediji", | ||||
|   "account.mention": "Pomeni korisnika @{name}", | ||||
|   "account.moved_to": "{name} se pomerio na:", | ||||
|   "account.mute": "Mutiraj @{name}", | ||||
|   "account.mute": "Ućutkaj korisnika @{name}", | ||||
|   "account.mute_notifications": "Isključi obaveštenja od korisnika @{name}", | ||||
|   "account.posts": "Statusa", | ||||
|   "account.report": "Prijavi @{name}", | ||||
|  | @ -21,7 +21,7 @@ | |||
|   "account.unblock": "Odblokiraj korisnika @{name}", | ||||
|   "account.unblock_domain": "Odblokiraj domen {domain}", | ||||
|   "account.unfollow": "Otprati", | ||||
|   "account.unmute": "Odmutiraj @{name}", | ||||
|   "account.unmute": "Ukloni ućutkavanje korisniku @{name}", | ||||
|   "account.unmute_notifications": "Uključi nazad obaveštenja od korisnika @{name}", | ||||
|   "account.view_full_profile": "Vidi ceo profil", | ||||
|   "boost_modal.combo": "Možete pritisnuti {combo} da preskočite ovo sledeći put", | ||||
|  | @ -37,10 +37,10 @@ | |||
|   "column.follow_requests": "Zahtevi za praćenje", | ||||
|   "column.home": "Početna", | ||||
|   "column.lists": "Liste", | ||||
|   "column.mutes": "Mutirani korisnici", | ||||
|   "column.mutes": "Ućutkani korisnici", | ||||
|   "column.notifications": "Obaveštenja", | ||||
|   "column.pins": "Prikačeni tutovi", | ||||
|   "column.public": "Združena lajna", | ||||
|   "column.public": "Federisana lajna", | ||||
|   "column_back_button.label": "Nazad", | ||||
|   "column_header.hide_settings": "Sakrij postavke", | ||||
|   "column_header.moveLeft_settings": "Pomeri kolonu ulevo", | ||||
|  | @ -50,6 +50,7 @@ | |||
|   "column_header.unpin": "Otkači", | ||||
|   "column_subheading.navigation": "Navigacija", | ||||
|   "column_subheading.settings": "Postavke", | ||||
|   "compose_form.hashtag_warning": "This toot won't be listed under any hashtag as it is unlisted. Only public toots can be searched by hashtag.", | ||||
|   "compose_form.lock_disclaimer": "Vaš nalog nije {locked}. Svako može da Vas zaprati i da vidi objave namenjene samo Vašim pratiocima.", | ||||
|   "compose_form.lock_disclaimer.lock": "zaključan", | ||||
|   "compose_form.placeholder": "Šta Vam je na umu?", | ||||
|  | @ -66,9 +67,9 @@ | |||
|   "confirmations.delete_list.confirm": "Obriši", | ||||
|   "confirmations.delete_list.message": "Da li ste sigurni da želite da bespovratno obrišete ovu listu?", | ||||
|   "confirmations.domain_block.confirm": "Sakrij ceo domen", | ||||
|   "confirmations.domain_block.message": "Da li ste stvarno, stvarno sigurno da želite da blokirate ceo domen {domain}? U većini slučajeva, par dobrih blokiranja ili mutiranja su dovoljna i preporučljiva.", | ||||
|   "confirmations.mute.confirm": "Mutiraj", | ||||
|   "confirmations.mute.message": "Da li stvarno želite da mutirate korisnika {name}?", | ||||
|   "confirmations.domain_block.message": "Da li ste stvarno, stvarno sigurno da želite da blokirate ceo domen {domain}? U većini slučajeva, par dobrih blokiranja ili ućutkavanja su dovoljna i preporučljiva.", | ||||
|   "confirmations.mute.confirm": "Ućutkaj", | ||||
|   "confirmations.mute.message": "Da li stvarno želite da ućutkate korisnika {name}?", | ||||
|   "confirmations.unfollow.confirm": "Otprati", | ||||
|   "confirmations.unfollow.message": "Da li ste sigurni da želite da otpratite korisnika {name}?", | ||||
|   "embed.instructions": "Ugradi ovaj status na Vaš veb sajt kopiranjem koda ispod.", | ||||
|  | @ -148,10 +149,10 @@ | |||
|   "navigation_bar.keyboard_shortcuts": "Prečice na tastaturi", | ||||
|   "navigation_bar.lists": "Liste", | ||||
|   "navigation_bar.logout": "Odjava", | ||||
|   "navigation_bar.mutes": "Mutirani korisnici", | ||||
|   "navigation_bar.mutes": "Ućutkani korisnici", | ||||
|   "navigation_bar.pins": "Prikačeni tutovi", | ||||
|   "navigation_bar.preferences": "Podešavanja", | ||||
|   "navigation_bar.public_timeline": "Združena lajna", | ||||
|   "navigation_bar.public_timeline": "Federisana lajna", | ||||
|   "notification.favourite": "{name} je stavio Vaš status kao omiljeni", | ||||
|   "notification.follow": "{name} Vas je zapratio", | ||||
|   "notification.mention": "{name} Vas je pomenuo", | ||||
|  | @ -169,7 +170,7 @@ | |||
|   "notifications.column_settings.sound": "Puštaj zvuk", | ||||
|   "onboarding.done": "Gotovo", | ||||
|   "onboarding.next": "Sledeće", | ||||
|   "onboarding.page_five.public_timelines": "Lokalna lajna prikazuje sve javne statuse od svih na domenu {domain}. Združena lajna prikazuje javne statuse od svih ljudi koje prate korisnici sa domena {domain}. Ovo su javne lajne, sjajan način da otkrijete nove ljude.", | ||||
|   "onboarding.page_five.public_timelines": "Lokalna lajna prikazuje sve javne statuse od svih na domenu {domain}. Federisana lajna prikazuje javne statuse od svih ljudi koje prate korisnici sa domena {domain}. Ovo su javne lajne, sjajan način da otkrijete nove ljude.", | ||||
|   "onboarding.page_four.home": "Početna lajna prikazuje statuse ljudi koje Vi pratite.", | ||||
|   "onboarding.page_four.notifications": "Kolona sa obaveštenjima Vam prikazuje kada neko priča sa Vama.", | ||||
|   "onboarding.page_one.federation": "Mastodont je mreža nezavisnih servera koji se uvezuju da naprave jednu veću društvenu mrežu. Ove servere zovemo instancama.", | ||||
|  | @ -213,6 +214,7 @@ | |||
|   "search_popout.tips.user": "korisnik", | ||||
|   "search_results.total": "{count, number} {count, plural, one {rezultat} few {rezultata} other {rezultata}}", | ||||
|   "standalone.public_title": "Pogled iznutra...", | ||||
|   "status.block": "Block @{name}", | ||||
|   "status.cannot_reblog": "Ovaj status ne može da se podrži", | ||||
|   "status.delete": "Obriši", | ||||
|   "status.embed": "Ugradi na sajt", | ||||
|  | @ -221,7 +223,8 @@ | |||
|   "status.media_hidden": "Multimedija sakrivena", | ||||
|   "status.mention": "Pomeni korisnika @{name}", | ||||
|   "status.more": "Još", | ||||
|   "status.mute_conversation": "Mutiraj prepisku", | ||||
|   "status.mute": "Mute @{name}", | ||||
|   "status.mute_conversation": "Ućutkaj prepisku", | ||||
|   "status.open": "Proširi ovaj status", | ||||
|   "status.pin": "Prikači na profil", | ||||
|   "status.reblog": "Podrži", | ||||
|  | @ -237,7 +240,7 @@ | |||
|   "status.unmute_conversation": "Uključi prepisku", | ||||
|   "status.unpin": "Otkači sa profila", | ||||
|   "tabs_bar.compose": "Napiši", | ||||
|   "tabs_bar.federated_timeline": "Združeno", | ||||
|   "tabs_bar.federated_timeline": "Federisano", | ||||
|   "tabs_bar.home": "Početna", | ||||
|   "tabs_bar.local_timeline": "Lokalno", | ||||
|   "tabs_bar.notifications": "Obaveštenja", | ||||
|  |  | |||
|  | @ -11,7 +11,7 @@ | |||
|   "account.media": "Медији", | ||||
|   "account.mention": "Помени корисника @{name}", | ||||
|   "account.moved_to": "{name} се померио на:", | ||||
|   "account.mute": "Мутирај @{name}", | ||||
|   "account.mute": "Ућуткај корисника @{name}", | ||||
|   "account.mute_notifications": "Искључи обавештења од корисника @{name}", | ||||
|   "account.posts": "Статуса", | ||||
|   "account.report": "Пријави @{name}", | ||||
|  | @ -21,7 +21,7 @@ | |||
|   "account.unblock": "Одблокирај корисника @{name}", | ||||
|   "account.unblock_domain": "Одблокирај домен {domain}", | ||||
|   "account.unfollow": "Отпрати", | ||||
|   "account.unmute": "Одмутирај @{name}", | ||||
|   "account.unmute": "Уклони ућуткавање кориснику @{name}", | ||||
|   "account.unmute_notifications": "Укључи назад обавештења од корисника @{name}", | ||||
|   "account.view_full_profile": "Види цео профил", | ||||
|   "boost_modal.combo": "Можете притиснути {combo} да прескочите ово следећи пут", | ||||
|  | @ -37,10 +37,10 @@ | |||
|   "column.follow_requests": "Захтеви за праћење", | ||||
|   "column.home": "Почетна", | ||||
|   "column.lists": "Листе", | ||||
|   "column.mutes": "Мутирани корисници", | ||||
|   "column.mutes": "Ућуткани корисници", | ||||
|   "column.notifications": "Обавештења", | ||||
|   "column.pins": "Прикачени тутови", | ||||
|   "column.public": "Здружена лајна", | ||||
|   "column.public": "Федерисана лајна", | ||||
|   "column_back_button.label": "Назад", | ||||
|   "column_header.hide_settings": "Сакриј поставке", | ||||
|   "column_header.moveLeft_settings": "Помери колону улево", | ||||
|  | @ -67,9 +67,9 @@ | |||
|   "confirmations.delete_list.confirm": "Обриши", | ||||
|   "confirmations.delete_list.message": "Да ли сте сигурни да желите да бесповратно обришете ову листу?", | ||||
|   "confirmations.domain_block.confirm": "Сакриј цео домен", | ||||
|   "confirmations.domain_block.message": "Да ли сте стварно, стварно сигурно да желите да блокирате цео домен {domain}? У већини случајева, пар добрих блокирања или мутирања су довољна и препоручљива.", | ||||
|   "confirmations.mute.confirm": "Мутирај", | ||||
|   "confirmations.mute.message": "Да ли стварно желите да мутирате корисника {name}?", | ||||
|   "confirmations.domain_block.message": "Да ли сте стварно, стварно сигурно да желите да блокирате цео домен {domain}? У већини случајева, пар добрих блокирања или ућуткавања су довољна и препоручљива.", | ||||
|   "confirmations.mute.confirm": "Ућуткај", | ||||
|   "confirmations.mute.message": "Да ли стварно желите да ућуткате корисника {name}?", | ||||
|   "confirmations.unfollow.confirm": "Отпрати", | ||||
|   "confirmations.unfollow.message": "Да ли сте сигурни да желите да отпратите корисника {name}?", | ||||
|   "embed.instructions": "Угради овај статус на Ваш веб сајт копирањем кода испод.", | ||||
|  | @ -149,10 +149,10 @@ | |||
|   "navigation_bar.keyboard_shortcuts": "Пречице на тастатури", | ||||
|   "navigation_bar.lists": "Листе", | ||||
|   "navigation_bar.logout": "Одјава", | ||||
|   "navigation_bar.mutes": "Мутирани корисници", | ||||
|   "navigation_bar.mutes": "Ућуткани корисници", | ||||
|   "navigation_bar.pins": "Прикачени тутови", | ||||
|   "navigation_bar.preferences": "Подешавања", | ||||
|   "navigation_bar.public_timeline": "Здружена лајна", | ||||
|   "navigation_bar.public_timeline": "Федерисана лајна", | ||||
|   "notification.favourite": "{name} је ставио Ваш статус као омиљени", | ||||
|   "notification.follow": "{name} Вас је запратио", | ||||
|   "notification.mention": "{name} Вас је поменуо", | ||||
|  | @ -170,7 +170,7 @@ | |||
|   "notifications.column_settings.sound": "Пуштај звук", | ||||
|   "onboarding.done": "Готово", | ||||
|   "onboarding.next": "Следеће", | ||||
|   "onboarding.page_five.public_timelines": "Локална лајна приказује све јавне статусе од свих на домену {domain}. Здружена лајна приказује јавне статусе од свих људи које прате корисници са домена {domain}. Ово су јавне лајне, сјајан начин да откријете нове људе.", | ||||
|   "onboarding.page_five.public_timelines": "Локална лајна приказује све јавне статусе од свих на домену {domain}. Федерисана лајна приказује јавне статусе од свих људи које прате корисници са домена {domain}. Ово су јавне лајне, сјајан начин да откријете нове људе.", | ||||
|   "onboarding.page_four.home": "Почетна лајна приказује статусе људи које Ви пратите.", | ||||
|   "onboarding.page_four.notifications": "Колона са обавештењима Вам приказује када неко прича са Вама.", | ||||
|   "onboarding.page_one.federation": "Мастодонт је мрежа независних сервера који се увезују да направе једну већу друштвену мрежу. Ове сервере зовемо инстанцама.", | ||||
|  | @ -224,7 +224,7 @@ | |||
|   "status.mention": "Помени корисника @{name}", | ||||
|   "status.more": "Још", | ||||
|   "status.mute": "Mute @{name}", | ||||
|   "status.mute_conversation": "Мутирај преписку", | ||||
|   "status.mute_conversation": "Ућуткај преписку", | ||||
|   "status.open": "Прошири овај статус", | ||||
|   "status.pin": "Прикачи на профил", | ||||
|   "status.reblog": "Подржи", | ||||
|  | @ -240,7 +240,7 @@ | |||
|   "status.unmute_conversation": "Укључи преписку", | ||||
|   "status.unpin": "Откачи са профила", | ||||
|   "tabs_bar.compose": "Напиши", | ||||
|   "tabs_bar.federated_timeline": "Здружено", | ||||
|   "tabs_bar.federated_timeline": "Федерисано", | ||||
|   "tabs_bar.home": "Почетна", | ||||
|   "tabs_bar.local_timeline": "Локално", | ||||
|   "tabs_bar.notifications": "Обавештења", | ||||
|  |  | |||
|  | @ -64,8 +64,8 @@ | |||
|   "confirmations.block.message": "你確定要封鎖 {name} ?", | ||||
|   "confirmations.delete.confirm": "刪除", | ||||
|   "confirmations.delete.message": "你確定要刪除這個狀態?", | ||||
|   "confirmations.delete_list.confirm": "Delete", | ||||
|   "confirmations.delete_list.message": "Are you sure you want to permanently delete this list?", | ||||
|   "confirmations.delete_list.confirm": "刪除", | ||||
|   "confirmations.delete_list.message": "確定要永久性地刪除這個名單嗎?", | ||||
|   "confirmations.domain_block.confirm": "隱藏整個網域", | ||||
|   "confirmations.domain_block.message": "你真的真的確定要隱藏整個 {domain} ?多數情況下,比較推薦封鎖或消音幾個特定目標就好。", | ||||
|   "confirmations.mute.confirm": "消音", | ||||
|  | @ -128,14 +128,14 @@ | |||
|   "lightbox.close": "關閉", | ||||
|   "lightbox.next": "繼續", | ||||
|   "lightbox.previous": "回退", | ||||
|   "lists.account.add": "Add to list", | ||||
|   "lists.account.remove": "Remove from list", | ||||
|   "lists.delete": "Delete list", | ||||
|   "lists.edit": "Edit list", | ||||
|   "lists.new.create": "Add list", | ||||
|   "lists.new.title_placeholder": "New list title", | ||||
|   "lists.search": "Search among people you follow", | ||||
|   "lists.subheading": "Your lists", | ||||
|   "lists.account.add": "加到名單裡", | ||||
|   "lists.account.remove": "從名單中移除", | ||||
|   "lists.delete": "刪除名單", | ||||
|   "lists.edit": "修改名單", | ||||
|   "lists.new.create": "新增名單", | ||||
|   "lists.new.title_placeholder": "名單名稱", | ||||
|   "lists.search": "搜尋您關注的使用者", | ||||
|   "lists.subheading": "您的名單", | ||||
|   "loading_indicator.label": "讀取中...", | ||||
|   "media_gallery.toggle_visible": "切換可見性", | ||||
|   "missing_indicator.label": "找不到", | ||||
|  | @ -146,8 +146,8 @@ | |||
|   "navigation_bar.favourites": "最愛", | ||||
|   "navigation_bar.follow_requests": "關注請求", | ||||
|   "navigation_bar.info": "關於本站", | ||||
|   "navigation_bar.keyboard_shortcuts": "Keyboard shortcuts", | ||||
|   "navigation_bar.lists": "Lists", | ||||
|   "navigation_bar.keyboard_shortcuts": "快速鍵", | ||||
|   "navigation_bar.lists": "名單", | ||||
|   "navigation_bar.logout": "登出", | ||||
|   "navigation_bar.mutes": "消音的使用者", | ||||
|   "navigation_bar.pins": "置頂貼文", | ||||
|  |  | |||
|  | @ -398,10 +398,12 @@ | |||
|     } | ||||
|   } | ||||
| 
 | ||||
|   &__content { | ||||
|     max-width: calc(100% - 90px); | ||||
|   } | ||||
| 
 | ||||
|   &__title { | ||||
|     overflow: hidden; | ||||
|     text-overflow: ellipsis; | ||||
|     white-space: nowrap; | ||||
|     word-wrap: break-word; | ||||
|   } | ||||
| 
 | ||||
|   &__timestamp { | ||||
|  | @ -415,7 +417,7 @@ | |||
|     color: $ui-primary-color; | ||||
|     font-family: 'mastodon-font-monospace', monospace; | ||||
|     font-size: 12px; | ||||
|     white-space: nowrap; | ||||
|     word-wrap: break-word; | ||||
|     min-height: 20px; | ||||
|   } | ||||
| 
 | ||||
|  |  | |||
|  | @ -126,18 +126,18 @@ class User < ApplicationRecord | |||
|   end | ||||
| 
 | ||||
|   def confirm | ||||
|     return if confirmed? | ||||
|     new_user = !confirmed? | ||||
| 
 | ||||
|     super | ||||
|     update_statistics! | ||||
|     update_statistics! if new_user | ||||
|   end | ||||
| 
 | ||||
|   def confirm! | ||||
|     return if confirmed? | ||||
|     new_user = !confirmed? | ||||
| 
 | ||||
|     skip_confirmation! | ||||
|     save! | ||||
|     update_statistics! | ||||
|     update_statistics! if new_user | ||||
|   end | ||||
| 
 | ||||
|   def promote! | ||||
|  |  | |||
|  | @ -0,0 +1,22 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| class ActivityPub::DeleteActorSerializer < ActiveModel::Serializer | ||||
|   attributes :id, :type, :actor | ||||
|   attribute :virtual_object, key: :object | ||||
| 
 | ||||
|   def id | ||||
|     [ActivityPub::TagManager.instance.uri_for(object), '#delete'].join | ||||
|   end | ||||
| 
 | ||||
|   def type | ||||
|     'Delete' | ||||
|   end | ||||
| 
 | ||||
|   def actor | ||||
|     ActivityPub::TagManager.instance.uri_for(object) | ||||
|   end | ||||
| 
 | ||||
|   def virtual_object | ||||
|     actor | ||||
|   end | ||||
| end | ||||
|  | @ -27,7 +27,7 @@ class REST::InstanceSerializer < ActiveModel::Serializer | |||
|   end | ||||
| 
 | ||||
|   def thumbnail | ||||
|     full_asset_url(instance_presenter.thumbnail.file.url) if instance_presenter.thumbnail | ||||
|     instance_presenter.thumbnail ? full_asset_url(instance_presenter.thumbnail.file.url) : full_pack_url('preview.jpg') | ||||
|   end | ||||
| 
 | ||||
|   def max_toot_chars | ||||
|  |  | |||
|  | @ -17,9 +17,7 @@ class BatchedRemoveStatusService < BaseService | |||
| 
 | ||||
|     @stream_entry_batches  = [] | ||||
|     @salmon_batches        = [] | ||||
|     @activity_json_batches = [] | ||||
|     @json_payloads         = statuses.map { |s| [s.id, Oj.dump(event: :delete, payload: s.id.to_s)] }.to_h | ||||
|     @activity_json         = {} | ||||
|     @activity_xml          = {} | ||||
| 
 | ||||
|     # Ensure that rendered XML reflects destroyed state | ||||
|  | @ -32,10 +30,7 @@ class BatchedRemoveStatusService < BaseService | |||
|       unpush_from_home_timelines(account, account_statuses) | ||||
|       unpush_from_list_timelines(account, account_statuses) | ||||
| 
 | ||||
|       if account.local? | ||||
|         batch_stream_entries(account, account_statuses) | ||||
|         batch_activity_json(account, account_statuses) | ||||
|       end | ||||
|       batch_stream_entries(account, account_statuses) if account.local? | ||||
|     end | ||||
| 
 | ||||
|     # Cannot be batched | ||||
|  | @ -47,7 +42,6 @@ class BatchedRemoveStatusService < BaseService | |||
| 
 | ||||
|     Pubsubhubbub::RawDistributionWorker.push_bulk(@stream_entry_batches) { |batch| batch } | ||||
|     NotificationWorker.push_bulk(@salmon_batches) { |batch| batch } | ||||
|     ActivityPub::DeliveryWorker.push_bulk(@activity_json_batches) { |batch| batch } | ||||
|   end | ||||
| 
 | ||||
|   private | ||||
|  | @ -58,22 +52,6 @@ class BatchedRemoveStatusService < BaseService | |||
|     end | ||||
|   end | ||||
| 
 | ||||
|   def batch_activity_json(account, statuses) | ||||
|     account.followers.inboxes.each do |inbox_url| | ||||
|       statuses.each do |status| | ||||
|         @activity_json_batches << [build_json(status), account.id, inbox_url] | ||||
|       end | ||||
|     end | ||||
| 
 | ||||
|     statuses.each do |status| | ||||
|       other_recipients = (status.mentions + status.reblogs).map(&:account).reject(&:local?).select(&:activitypub?).uniq(&:id) | ||||
| 
 | ||||
|       other_recipients.each do |target_account| | ||||
|         @activity_json_batches << [build_json(status), account.id, target_account.inbox_url] | ||||
|       end | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
|   def unpush_from_home_timelines(account, statuses) | ||||
|     recipients = account.followers.local.to_a | ||||
| 
 | ||||
|  | @ -134,23 +112,9 @@ class BatchedRemoveStatusService < BaseService | |||
|     Redis.current | ||||
|   end | ||||
| 
 | ||||
|   def build_json(status) | ||||
|     return @activity_json[status.id] if @activity_json.key?(status.id) | ||||
| 
 | ||||
|     @activity_json[status.id] = sign_json(status, ActiveModelSerializers::SerializableResource.new( | ||||
|       status, | ||||
|       serializer: status.reblog? ? ActivityPub::UndoAnnounceSerializer : ActivityPub::DeleteSerializer, | ||||
|       adapter: ActivityPub::Adapter | ||||
|     ).as_json) | ||||
|   end | ||||
| 
 | ||||
|   def build_xml(stream_entry) | ||||
|     return @activity_xml[stream_entry.id] if @activity_xml.key?(stream_entry.id) | ||||
| 
 | ||||
|     @activity_xml[stream_entry.id] = stream_entry_to_xml(stream_entry) | ||||
|   end | ||||
| 
 | ||||
|   def sign_json(status, json) | ||||
|     Oj.dump(ActivityPub::LinkedDataSignature.new(json).sign!(status.account)) | ||||
|   end | ||||
| end | ||||
|  |  | |||
|  | @ -50,7 +50,7 @@ class FetchAtomService < BaseService | |||
|         @unsupported_activity = true | ||||
|         nil | ||||
|       end | ||||
|     elsif @response['Link'] && !terminal | ||||
|     elsif @response['Link'] && !terminal && link_header.find_link(%w(rel alternate)) | ||||
|       process_headers | ||||
|     elsif @response.mime_type == 'text/html' && !terminal | ||||
|       process_html | ||||
|  | @ -70,8 +70,6 @@ class FetchAtomService < BaseService | |||
|   end | ||||
| 
 | ||||
|   def process_headers | ||||
|     link_header = LinkHeader.parse(@response['Link'].is_a?(Array) ? @response['Link'].first : @response['Link']) | ||||
| 
 | ||||
|     json_link = link_header.find_link(%w(rel alternate), %w(type application/activity+json)) || link_header.find_link(%w(rel alternate), ['type', 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"']) | ||||
|     atom_link = link_header.find_link(%w(rel alternate), %w(type application/atom+xml)) | ||||
| 
 | ||||
|  | @ -80,4 +78,8 @@ class FetchAtomService < BaseService | |||
| 
 | ||||
|     result | ||||
|   end | ||||
| 
 | ||||
|   def link_header | ||||
|     @link_header ||= LinkHeader.parse(@response['Link'].is_a?(Array) ? @response['Link'].first : @response['Link']) | ||||
|   end | ||||
| end | ||||
|  |  | |||
|  | @ -22,6 +22,8 @@ class SuspendAccountService < BaseService | |||
|   end | ||||
| 
 | ||||
|   def purge_content! | ||||
|     ActivityPub::RawDistributionWorker.perform_async(delete_actor_json, @account.id) if @account.local? | ||||
| 
 | ||||
|     @account.statuses.reorder(nil).find_in_batches do |statuses| | ||||
|       BatchedRemoveStatusService.new.call(statuses) | ||||
|     end | ||||
|  | @ -54,4 +56,14 @@ class SuspendAccountService < BaseService | |||
|   def destroy_all(association) | ||||
|     association.in_batches.destroy_all | ||||
|   end | ||||
| 
 | ||||
|   def delete_actor_json | ||||
|     payload = ActiveModelSerializers::SerializableResource.new( | ||||
|       @account, | ||||
|       serializer: ActivityPub::DeleteActorSerializer, | ||||
|       adapter: ActivityPub::Adapter | ||||
|     ).as_json | ||||
| 
 | ||||
|     Oj.dump(ActivityPub::LinkedDataSignature.new(payload).sign!(@account)) | ||||
|   end | ||||
| end | ||||
|  |  | |||
|  | @ -160,6 +160,7 @@ pl: | |||
|         update_status: "%{name} zaktualizował wpis użytkownika %{target}" | ||||
|       title: Dziennik działań administracyjnych | ||||
|     custom_emojis: | ||||
|       by_domain: Według domeny | ||||
|       copied_msg: Pomyślnie utworzono lokalną kopię emoji | ||||
|       copy: Kopiuj | ||||
|       copy_failed_msg: Nie udało się utworzyć lokalnej kopii emoji | ||||
|  | @ -620,6 +621,7 @@ pl: | |||
|       private: Nie możesz przypiąć niepublicznego wpisu | ||||
|       reblog: Nie możesz przypiąć podbicia wpisu | ||||
|     show_more: Pokaż więcej | ||||
|     title: '%{name}: "%{quote}"' | ||||
|     visibilities: | ||||
|       private: Tylko dla śledzących | ||||
|       private_long: Widoczne tylko dla osób, które Cię śledzą | ||||
|  |  | |||
|  | @ -21,7 +21,7 @@ zh-TW: | |||
|         data: 資料 | ||||
|         display_name: 顯示名稱 | ||||
|         email: 電子信箱 | ||||
|         filtered_languages: 封鎖下面语言的文章 | ||||
|         filtered_languages: 封鎖下面語言的文章 | ||||
|         header: 個人頁面頂部 | ||||
|         locale: 語言 | ||||
|         locked: 將帳號轉為「私密」 | ||||
|  | @ -29,7 +29,16 @@ zh-TW: | |||
|         note: 簡介 | ||||
|         otp_attempt: 雙因子驗證碼 | ||||
|         password: 密碼 | ||||
|         setting_auto_play_gif: 自動播放 GIFs | ||||
|         setting_boost_modal: 轉推前跳出確認視窗 | ||||
|         setting_default_privacy: 文章預設隱私度 | ||||
|         setting_default_sensitive: 預設我的內容為敏感內容 | ||||
|         setting_delete_modal: 刪推前跳出確認視窗 | ||||
|         setting_noindex: 不被搜尋引擎檢索 | ||||
|         setting_reduce_motion: 減低動畫效果 | ||||
|         setting_system_font_ui: 使用系統預設字體 | ||||
|         setting_theme: 網站主題 | ||||
|         setting_unfollow_modal: 取消關注前跳出確認視窗 | ||||
|         type: 匯入資料類型 | ||||
|         username: 使用者名稱 | ||||
|       interactions: | ||||
|  |  | |||
|  | @ -409,8 +409,8 @@ sr-Latn: | |||
|   exports: | ||||
|     blocks: Blokirali ste | ||||
|     csv: CSV | ||||
|     follows: PRatite | ||||
|     mutes: Mutirali ste | ||||
|     follows: Pratite | ||||
|     mutes: Ućutkali ste | ||||
|     storage: Multimedijalno skladište | ||||
|   followers: | ||||
|     domain: Domen | ||||
|  | @ -441,7 +441,7 @@ sr-Latn: | |||
|     types: | ||||
|       blocking: Lista blokiranja | ||||
|       following: Lista pratilaca | ||||
|       muting: Lista mutiranih | ||||
|       muting: Lista ućutkanih | ||||
|     upload: Otpremi | ||||
|   in_memoriam_html: In Memoriam. | ||||
|   invites: | ||||
|  |  | |||
|  | @ -409,8 +409,8 @@ sr: | |||
|   exports: | ||||
|     blocks: Блокирали сте | ||||
|     csv: CSV | ||||
|     follows: ПРатите | ||||
|     mutes: Мутирали сте | ||||
|     follows: Пратите | ||||
|     mutes: Ућуткали сте | ||||
|     storage: Мултимедијално складиште | ||||
|   followers: | ||||
|     domain: Домен | ||||
|  | @ -441,7 +441,7 @@ sr: | |||
|     types: | ||||
|       blocking: Листа блокирања | ||||
|       following: Листа пратилаца | ||||
|       muting: Листа мутираних | ||||
|       muting: Листа ућутканих | ||||
|     upload: Отпреми | ||||
|   in_memoriam_html: In Memoriam. | ||||
|   invites: | ||||
|  |  | |||
|  | @ -55,7 +55,7 @@ zh-TW: | |||
|       perform_full_suspension: 進行停權 | ||||
|       profile_url: 個人檔案網址 | ||||
|       public: 公開 | ||||
|       push_subscription_expires: PuSH 訂閱逾期 | ||||
|       push_subscription_expires: 推播訂閱過期 | ||||
|       salmon_url: Salmon URL | ||||
|       silence: 靜音 | ||||
|       statuses: 狀態 | ||||
|  | @ -133,12 +133,14 @@ zh-TW: | |||
|     forgot_password: 忘記密碼? | ||||
|     login: 登入 | ||||
|     logout: 登出 | ||||
|     migrate_account: 轉移到另一個帳號 | ||||
|     migrate_account_html: 想要將這個帳號指向另一個帳號可到<a href="%{path}">到這裡設定</a>。 | ||||
|     register: 註冊 | ||||
|     resend_confirmation: 重寄驗證信 | ||||
|     reset_password: 重設密碼 | ||||
|     set_new_password: 設定新密碼 | ||||
|   authorize_follow: | ||||
|     error: 對不起,尋找這個跨站使用者的過程發生錯誤 | ||||
|     error: 對不起,搜尋遠端使用者出現錯誤 | ||||
|     follow: 關注 | ||||
|     title: 關注 %{acct} | ||||
|   datetime: | ||||
|  | @ -165,7 +167,16 @@ zh-TW: | |||
|     blocks: 您封鎖的使用者 | ||||
|     csv: CSV | ||||
|     follows: 您關注的使用者 | ||||
|     mutes: 您靜音的使用者 | ||||
|     storage: 儲存空間大小 | ||||
|   followers: | ||||
|     domain: 網域 | ||||
|     explanation_html: 為確保個人隱私,您必須知道有哪些使用者正關注你。<strong>您的私密內容會被發送到所有您有被關注的服務站上</strong>。如果您不信任這些服務站的管理者,您可以選擇檢查或刪除您的關注者。 | ||||
|     followers_count: 關注者數 | ||||
|     lock_link: 鎖住你的帳號 | ||||
|     purge: 移除關注者 | ||||
|     unlocked_warning_html: 所有人都可以關注並檢索你的隱藏狀態。%{lock_link}以檢查或拒絕關注。 | ||||
|     unlocked_warning_title: 你的帳號是公開的 | ||||
|   generic: | ||||
|     changes_saved_msg: 已成功儲存修改 | ||||
|     powered_by: 網站由 %{link} 開發 | ||||
|  | @ -179,6 +190,7 @@ zh-TW: | |||
|     types: | ||||
|       blocking: 您封鎖的使用者名單 | ||||
|       following: 您關注的使用者名單 | ||||
|       muting: 您靜音的使用者名單 | ||||
|     upload: 上傳 | ||||
|   landing_strip_html: "<strong>%{name}</strong> 是一個在 %{link_to_root_path} 的使用者。只要您有任何 Mastodon 服務站、或者聯盟網站的帳號,便可以跨站關注此站使用者,或者與他們互動。" | ||||
|   landing_strip_signup_html: 如果您沒有這些帳號,歡迎在<a href="%{sign_up_path}">這裡註冊</a>。 | ||||
|  | @ -231,15 +243,26 @@ zh-TW: | |||
|     missing_resource: 無法找到資源 | ||||
|     proceed: 下一步 | ||||
|     prompt: 您希望關注︰ | ||||
|   sessions: | ||||
|     activity: 最近活動 | ||||
|     browser: 瀏覽器 | ||||
|     current_session: 目前的 session | ||||
|     description: "%{platform} 上的 %{browser}" | ||||
|     explanation: 這些是現在正登入於你的 Mastodon 帳號的瀏覽器。 | ||||
|     revoke: 取消 | ||||
|     revoke_success: Session 取消成功。 | ||||
|   settings: | ||||
|     authorized_apps: 已授權應用程式 | ||||
|     back: 回到 Mastodon | ||||
|     development: 開發 | ||||
|     edit_profile: 修改個人資料 | ||||
|     export: 匯出 | ||||
|     followers: 授權追蹤者 | ||||
|     import: 匯入 | ||||
|     notifications: 通知 | ||||
|     preferences: 偏好設定 | ||||
|     settings: 設定 | ||||
|     two_factor_authentication: 雙因子認證 | ||||
|     two_factor_authentication: 兩階段認證 | ||||
|   statuses: | ||||
|     open_in_web: 以網頁開啟 | ||||
|     over_character_limit: 超過了 %{max} 字的限制 | ||||
|  | @ -257,14 +280,14 @@ zh-TW: | |||
|       default: "%Y年%-m月%d日 %H:%M" | ||||
|   two_factor_authentication: | ||||
|     code_hint: 請輸入您認證器產生的代碼,以進行認證 | ||||
|     description_html: 當您啟用<strong>雙因子認證</strong>後,您登入時將需要使您手機、或其他種類認證器產生的代碼。 | ||||
|     description_html: 啟用<strong>兩階段認證</strong>後,登入時將需要使手機、或其他種類認證器產生的代碼。 | ||||
|     disable: 停用 | ||||
|     enable: 啟用 | ||||
|     enabled_success: 已成功啟用雙因子認證 | ||||
|     instructions_html: "<strong>請用您手機的認證器應用程式(如 Google Authenticator、Authy),掃描這裡的 QR 圖形碼</strong>。在雙因子認證啟用後,您登入時將須要使用此應用程式產生的認證碼。" | ||||
|     enabled_success: 已成功啟用兩階段認證 | ||||
|     instructions_html: "<strong>請用您手機的認證器應用程式(如 Google Authenticator、Authy),掃描這裡的 QR 圖形碼</strong>。在兩階段認證啟用後,您登入時將須要使用此應用程式產生的認證碼。" | ||||
|     manual_instructions: 如果您無法掃描 QR 圖形碼,請手動輸入︰ | ||||
|     setup: 設定 | ||||
|     wrong_code: 您輸入的認證碼並不正確!可能伺服器時間和您手機不一致,請檢查您手機的時間,或與本站管理員聯絡。 | ||||
|   users: | ||||
|     invalid_email: 信箱地址格式不正確 | ||||
|     invalid_otp_token: 雙因子認證碼不正確 | ||||
|     invalid_otp_token: 兩階段認證碼不正確 | ||||
|  |  | |||
|  | @ -1,6 +1,7 @@ | |||
| class AddIndexOnStreamEntries < ActiveRecord::Migration[5.1] | ||||
|   disable_ddl_transaction! | ||||
| 
 | ||||
|   def change | ||||
|     commit_db_transaction | ||||
|     add_index :stream_entries, [:account_id, :activity_type, :id], algorithm: :concurrently | ||||
|     remove_index :stream_entries, name: :index_stream_entries_on_account_id | ||||
|   end | ||||
|  |  | |||
|  | @ -1,6 +1,7 @@ | |||
| class MoreFasterIndexOnNotifications < ActiveRecord::Migration[5.1] | ||||
|   disable_ddl_transaction! | ||||
| 
 | ||||
|   def change | ||||
|     commit_db_transaction | ||||
|     add_index :notifications, [:account_id, :id], order: { id: :desc }, algorithm: :concurrently | ||||
|     remove_index :notifications, name: :index_notifications_on_id_and_account_id_and_activity_type | ||||
|   end | ||||
|  |  | |||
|  | @ -13,7 +13,7 @@ module Mastodon | |||
|     end | ||||
| 
 | ||||
|     def patch | ||||
|       0 | ||||
|       1 | ||||
|     end | ||||
| 
 | ||||
|     def pre | ||||
|  |  | |||
|  | @ -12,20 +12,40 @@ describe Auth::ConfirmationsController, type: :controller do | |||
|   end | ||||
| 
 | ||||
|   describe 'GET #show' do | ||||
|     let!(:user) { Fabricate(:user, confirmation_token: 'foobar', confirmed_at: nil) } | ||||
|     context 'when user is unconfirmed' do | ||||
|       let!(:user) { Fabricate(:user, confirmation_token: 'foobar', confirmed_at: nil) } | ||||
| 
 | ||||
|     before do | ||||
|       allow(BootstrapTimelineWorker).to receive(:perform_async) | ||||
|       @request.env['devise.mapping'] = Devise.mappings[:user] | ||||
|       get :show, params: { confirmation_token: 'foobar' } | ||||
|       before do | ||||
|         allow(BootstrapTimelineWorker).to receive(:perform_async) | ||||
|         @request.env['devise.mapping'] = Devise.mappings[:user] | ||||
|         get :show, params: { confirmation_token: 'foobar' } | ||||
|       end | ||||
| 
 | ||||
|       it 'redirects to login' do | ||||
|         expect(response).to redirect_to(new_user_session_path) | ||||
|       end | ||||
| 
 | ||||
|       it 'queues up bootstrapping of home timeline' do | ||||
|         expect(BootstrapTimelineWorker).to have_received(:perform_async).with(user.account_id) | ||||
|       end | ||||
|     end | ||||
| 
 | ||||
|     it 'redirects to login' do | ||||
|       expect(response).to redirect_to(new_user_session_path) | ||||
|     end | ||||
|     context 'when user is updating email' do | ||||
|       let!(:user) { Fabricate(:user, confirmation_token: 'foobar', unconfirmed_email: 'new-email@example.com') } | ||||
| 
 | ||||
|     it 'queues up bootstrapping of home timeline' do | ||||
|       expect(BootstrapTimelineWorker).to have_received(:perform_async).with(user.account_id) | ||||
|       before do | ||||
|         allow(BootstrapTimelineWorker).to receive(:perform_async) | ||||
|         @request.env['devise.mapping'] = Devise.mappings[:user] | ||||
|         get :show, params: { confirmation_token: 'foobar' } | ||||
|       end | ||||
| 
 | ||||
|       it 'redirects to login' do | ||||
|         expect(response).to redirect_to(new_user_session_path) | ||||
|       end | ||||
| 
 | ||||
|       it 'does not queue up bootstrapping of home timeline' do | ||||
|         expect(BootstrapTimelineWorker).to_not have_received(:perform_async) | ||||
|       end | ||||
|     end | ||||
|   end | ||||
| end | ||||
|  |  | |||
|  | @ -148,6 +148,14 @@ RSpec.describe User, type: :model do | |||
|     end | ||||
|   end | ||||
| 
 | ||||
|   describe '#confirm' do | ||||
|     it 'sets email to unconfirmed_email' do | ||||
|       user = Fabricate.build(:user, confirmed_at: Time.now.utc, unconfirmed_email: 'new-email@example.com') | ||||
|       user.confirm | ||||
|       expect(user.email).to eq 'new-email@example.com' | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
|   describe '#disable_two_factor!' do | ||||
|     it 'saves false for otp_required_for_login' do | ||||
|       user = Fabricate.build(:user, otp_required_for_login: true) | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue