mirror of
https://git.kescher.at/CatCatNya/catstodon.git
synced 2024-11-22 10:38:07 +01:00
Merge pull request #2580 from ClearlyClaire/glitch-soc/merge-upstream
Merge upstream changes up to e2d9635074
This commit is contained in:
commit
634acd07c4
108 changed files with 1442 additions and 594 deletions
|
@ -80,14 +80,12 @@ Rails/WhereExists:
|
|||
- 'app/lib/activitypub/activity/create.rb'
|
||||
- 'app/lib/delivery_failure_tracker.rb'
|
||||
- 'app/lib/feed_manager.rb'
|
||||
- 'app/lib/status_cache_hydrator.rb'
|
||||
- 'app/lib/suspicious_sign_in_detector.rb'
|
||||
- 'app/models/poll.rb'
|
||||
- 'app/models/session_activation.rb'
|
||||
- 'app/models/status.rb'
|
||||
- 'app/policies/status_policy.rb'
|
||||
- 'app/serializers/rest/announcement_serializer.rb'
|
||||
- 'app/serializers/rest/tag_serializer.rb'
|
||||
- 'app/services/activitypub/fetch_remote_status_service.rb'
|
||||
- 'app/services/vote_service.rb'
|
||||
- 'app/validators/reaction_validator.rb'
|
||||
|
@ -137,7 +135,6 @@ Style/FetchEnvVar:
|
|||
# AllowedMethods: redirect
|
||||
Style/FormatStringToken:
|
||||
Exclude:
|
||||
- 'app/models/privacy_policy.rb'
|
||||
- 'config/initializers/devise.rb'
|
||||
- 'lib/paperclip/color_extractor.rb'
|
||||
|
||||
|
|
|
@ -1 +1 @@
|
|||
3.2.2
|
||||
3.2.3
|
||||
|
|
|
@ -7,15 +7,15 @@
|
|||
ARG TARGETPLATFORM=${TARGETPLATFORM}
|
||||
ARG BUILDPLATFORM=${BUILDPLATFORM}
|
||||
|
||||
# Ruby image to use for base image, change with [--build-arg RUBY_VERSION="3.2.2"]
|
||||
ARG RUBY_VERSION="3.2.2"
|
||||
# Ruby image to use for base image, change with [--build-arg RUBY_VERSION="3.2.3"]
|
||||
ARG RUBY_VERSION="3.2.3"
|
||||
# # Node version to use in base image, change with [--build-arg NODE_MAJOR_VERSION="20"]
|
||||
ARG NODE_MAJOR_VERSION="20"
|
||||
# Debian image to use for base image, change with [--build-arg DEBIAN_VERSION="bookworm"]
|
||||
ARG DEBIAN_VERSION="bookworm"
|
||||
# Node image to use for base image based on combined variables (ex: 20-bookworm-slim)
|
||||
FROM docker.io/node:${NODE_MAJOR_VERSION}-${DEBIAN_VERSION}-slim as node
|
||||
# Ruby image to use for base image based on combined variables (ex: 3.2.2-slim-bookworm)
|
||||
# Ruby image to use for base image based on combined variables (ex: 3.2.3-slim-bookworm)
|
||||
FROM docker.io/ruby:${RUBY_VERSION}-slim-${DEBIAN_VERSION} as ruby
|
||||
|
||||
# Resulting version string is vX.X.X-MASTODON_VERSION_PRERELEASE+MASTODON_VERSION_METADATA
|
||||
|
|
|
@ -1,19 +1,35 @@
|
|||
## ActivityPub federation in Mastodon
|
||||
# Federation
|
||||
|
||||
## Supported federation protocols and standards
|
||||
|
||||
- [ActivityPub](https://www.w3.org/TR/activitypub/) (Server-to-Server)
|
||||
- [WebFinger](https://webfinger.net/)
|
||||
- [Http Signatures](https://datatracker.ietf.org/doc/html/draft-cavage-http-signatures)
|
||||
- [NodeInfo](https://nodeinfo.diaspora.software/)
|
||||
|
||||
## Supported FEPs
|
||||
|
||||
- [FEP-67ff: FEDERATION.md](https://codeberg.org/fediverse/fep/src/branch/main/fep/67ff/fep-67ff.md)
|
||||
- [FEP-f1d5: NodeInfo in Fediverse Software](https://codeberg.org/fediverse/fep/src/branch/main/fep/f1d5/fep-f1d5.md)
|
||||
- [FEP-8fcf: Followers collection synchronization across servers](https://codeberg.org/fediverse/fep/src/branch/main/fep/8fcf/fep-8fcf.md)
|
||||
- [FEP-5feb: Search indexing consent for actors](https://codeberg.org/fediverse/fep/src/branch/main/fep/5feb/fep-5feb.md)
|
||||
|
||||
## ActivityPub in Mastodon
|
||||
|
||||
Mastodon largely follows the ActivityPub server-to-server specification but it makes uses of some non-standard extensions, some of which are required for interacting with Mastodon at all.
|
||||
|
||||
Supported vocabulary: https://docs.joinmastodon.org/spec/activitypub/
|
||||
- [Supported ActivityPub vocabulary](https://docs.joinmastodon.org/spec/activitypub/)
|
||||
|
||||
### Required extensions
|
||||
|
||||
#### Webfinger
|
||||
#### WebFinger
|
||||
|
||||
In Mastodon, users are identified by a `username` and `domain` pair (e.g., `Gargron@mastodon.social`).
|
||||
This is used both for discovery and for unambiguously mentioning users across the fediverse. Furthermore, this is part of Mastodon's database design from its very beginnings.
|
||||
|
||||
As a result, Mastodon requires that each ActivityPub actor uniquely maps back to an `acct:` URI that can be resolved via WebFinger.
|
||||
|
||||
More information and examples are available at: https://docs.joinmastodon.org/spec/webfinger/
|
||||
- [WebFinger information and examples](https://docs.joinmastodon.org/spec/webfinger/)
|
||||
|
||||
#### HTTP Signatures
|
||||
|
||||
|
@ -21,11 +37,13 @@ In order to authenticate activities, Mastodon relies on HTTP Signatures, signing
|
|||
|
||||
Mastodon requires all `POST` requests to be signed, and MAY require `GET` requests to be signed, depending on the configuration of the Mastodon server.
|
||||
|
||||
More information on HTTP Signatures, as well as examples, can be found here: https://docs.joinmastodon.org/spec/security/#http
|
||||
- [HTTP Signatures information and examples](https://docs.joinmastodon.org/spec/security/#http)
|
||||
|
||||
### Optional extensions
|
||||
|
||||
- Linked-Data Signatures: https://docs.joinmastodon.org/spec/security/#ld
|
||||
- Bearcaps: https://docs.joinmastodon.org/spec/bearcaps/
|
||||
- Followers collection synchronization: https://codeberg.org/fediverse/fep/src/branch/main/fep/8fcf/fep-8fcf.md
|
||||
- Search indexing consent for actors: https://codeberg.org/fediverse/fep/src/branch/main/fep/5feb/fep-5feb.md
|
||||
- [Linked-Data Signatures](https://docs.joinmastodon.org/spec/security/#ld)
|
||||
- [Bearcaps](https://docs.joinmastodon.org/spec/bearcaps/)
|
||||
|
||||
### Additional documentation
|
||||
|
||||
- [Mastodon documentation](https://docs.joinmastodon.org/)
|
||||
|
|
10
Gemfile.lock
10
Gemfile.lock
|
@ -150,7 +150,7 @@ GEM
|
|||
erubi (~> 1.4)
|
||||
parser (>= 2.4)
|
||||
smart_properties
|
||||
bigdecimal (3.1.5)
|
||||
bigdecimal (3.1.6)
|
||||
bindata (2.4.15)
|
||||
binding_of_caller (1.0.0)
|
||||
debug_inspector (>= 0.0.1)
|
||||
|
@ -398,12 +398,12 @@ GEM
|
|||
activerecord
|
||||
kaminari-core (= 1.2.2)
|
||||
kaminari-core (1.2.2)
|
||||
kt-paperclip (7.2.1)
|
||||
kt-paperclip (7.2.2)
|
||||
activemodel (>= 4.2.0)
|
||||
activesupport (>= 4.2.0)
|
||||
marcel (~> 1.0.1)
|
||||
mime-types
|
||||
terrapin (~> 0.6.0)
|
||||
terrapin (>= 0.6.0, < 2.0)
|
||||
language_server-protocol (3.17.0.3)
|
||||
launchy (2.5.2)
|
||||
addressable (~> 2.8)
|
||||
|
@ -600,8 +600,8 @@ GEM
|
|||
rdf (3.3.1)
|
||||
bcp47_spec (~> 0.2)
|
||||
link_header (~> 0.0, >= 0.0.8)
|
||||
rdf-normalize (0.6.1)
|
||||
rdf (~> 3.2)
|
||||
rdf-normalize (0.7.0)
|
||||
rdf (~> 3.3)
|
||||
rdoc (6.6.2)
|
||||
psych (>= 4.0.0)
|
||||
redcarpet (3.6.0)
|
||||
|
|
|
@ -24,7 +24,7 @@ class ActivityPub::FollowersSynchronizationsController < ActivityPub::BaseContro
|
|||
end
|
||||
|
||||
def set_items
|
||||
@items = @account.followers.where(Account.arel_table[:uri].matches("#{Account.sanitize_sql_like(uri_prefix)}/%", false, true)).or(@account.followers.where(uri: uri_prefix)).pluck(:uri)
|
||||
@items = @account.followers.matches_uri_prefix(uri_prefix).pluck(:uri)
|
||||
end
|
||||
|
||||
def collection_presenter
|
||||
|
|
|
@ -6,7 +6,7 @@ module Admin
|
|||
|
||||
def index
|
||||
authorize :audit_log, :index?
|
||||
@auditable_accounts = Account.where(id: Admin::ActionLog.select('distinct account_id')).select(:id, :username)
|
||||
@auditable_accounts = Account.auditable.select(:id, :username)
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
@ -21,7 +21,7 @@ class Api::V1::Accounts::FollowerAccountsController < Api::BaseController
|
|||
return [] if hide_results?
|
||||
|
||||
scope = default_accounts
|
||||
scope = scope.where.not(id: current_account.excluded_from_timeline_account_ids) unless current_account.nil? || current_account.id == @account.id
|
||||
scope = scope.not_excluded_by_account(current_account) unless current_account.nil? || current_account.id == @account.id
|
||||
scope.merge(paginated_follows).to_a
|
||||
end
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ class Api::V1::Accounts::FollowingAccountsController < Api::BaseController
|
|||
return [] if hide_results?
|
||||
|
||||
scope = default_accounts
|
||||
scope = scope.where.not(id: current_account.excluded_from_timeline_account_ids) unless current_account.nil? || current_account.id == @account.id
|
||||
scope = scope.not_excluded_by_account(current_account) unless current_account.nil? || current_account.id == @account.id
|
||||
scope.merge(paginated_follows).to_a
|
||||
end
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ class Api::V1::Statuses::FavouritedByAccountsController < Api::V1::Statuses::Bas
|
|||
|
||||
def load_accounts
|
||||
scope = default_accounts
|
||||
scope = scope.where.not(id: current_account.excluded_from_timeline_account_ids) unless current_account.nil?
|
||||
scope = scope.not_excluded_by_account(current_account) unless current_account.nil?
|
||||
scope.merge(paginated_favourites).to_a
|
||||
end
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ class Api::V1::Statuses::RebloggedByAccountsController < Api::V1::Statuses::Base
|
|||
|
||||
def load_accounts
|
||||
scope = default_accounts
|
||||
scope = scope.where.not(id: current_account.excluded_from_timeline_account_ids) unless current_account.nil?
|
||||
scope = scope.not_excluded_by_account(current_account) unless current_account.nil?
|
||||
scope.merge(paginated_statuses).to_a
|
||||
end
|
||||
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class Auth::SessionsController < Devise::SessionsController
|
||||
include Redisable
|
||||
|
||||
MAX_2FA_ATTEMPTS_PER_HOUR = 10
|
||||
|
||||
layout 'auth'
|
||||
|
||||
skip_before_action :check_self_destruct!
|
||||
|
@ -135,9 +139,23 @@ class Auth::SessionsController < Devise::SessionsController
|
|||
session.delete(:attempt_user_updated_at)
|
||||
end
|
||||
|
||||
def clear_2fa_attempt_from_user(user)
|
||||
redis.del(second_factor_attempts_key(user))
|
||||
end
|
||||
|
||||
def check_second_factor_rate_limits(user)
|
||||
attempts, = redis.multi do |multi|
|
||||
multi.incr(second_factor_attempts_key(user))
|
||||
multi.expire(second_factor_attempts_key(user), 1.hour)
|
||||
end
|
||||
|
||||
attempts >= MAX_2FA_ATTEMPTS_PER_HOUR
|
||||
end
|
||||
|
||||
def on_authentication_success(user, security_measure)
|
||||
@on_authentication_success_called = true
|
||||
|
||||
clear_2fa_attempt_from_user(user)
|
||||
clear_attempt_from_session
|
||||
|
||||
user.update_sign_in!(new_sign_in: true)
|
||||
|
@ -168,5 +186,14 @@ class Auth::SessionsController < Devise::SessionsController
|
|||
ip: request.remote_ip,
|
||||
user_agent: request.user_agent
|
||||
)
|
||||
|
||||
# Only send a notification email every hour at most
|
||||
return if redis.set("2fa_failure_notification:#{user.id}", '1', ex: 1.hour, get: true).present?
|
||||
|
||||
UserMailer.failed_2fa(user, request.remote_ip, request.user_agent, Time.now.utc).deliver_later!
|
||||
end
|
||||
|
||||
def second_factor_attempts_key(user)
|
||||
"2fa_auth_attempts:#{user.id}:#{Time.now.utc.hour}"
|
||||
end
|
||||
end
|
||||
|
|
|
@ -66,6 +66,11 @@ module Auth::TwoFactorAuthenticationConcern
|
|||
end
|
||||
|
||||
def authenticate_with_two_factor_via_otp(user)
|
||||
if check_second_factor_rate_limits(user)
|
||||
flash.now[:alert] = I18n.t('users.rate_limited')
|
||||
return prompt_for_two_factor(user)
|
||||
end
|
||||
|
||||
if valid_otp_attempt?(user)
|
||||
on_authentication_success(user, :otp)
|
||||
else
|
||||
|
|
|
@ -155,7 +155,7 @@ module JsonLdHelper
|
|||
end
|
||||
end
|
||||
|
||||
def fetch_resource(uri, id, on_behalf_of = nil)
|
||||
def fetch_resource(uri, id, on_behalf_of = nil, request_options: {})
|
||||
unless id
|
||||
json = fetch_resource_without_id_validation(uri, on_behalf_of)
|
||||
|
||||
|
@ -164,14 +164,14 @@ module JsonLdHelper
|
|||
uri = json['id']
|
||||
end
|
||||
|
||||
json = fetch_resource_without_id_validation(uri, on_behalf_of)
|
||||
json = fetch_resource_without_id_validation(uri, on_behalf_of, request_options: request_options)
|
||||
json.present? && json['id'] == uri ? json : nil
|
||||
end
|
||||
|
||||
def fetch_resource_without_id_validation(uri, on_behalf_of = nil, raise_on_temporary_error = false)
|
||||
def fetch_resource_without_id_validation(uri, on_behalf_of = nil, raise_on_temporary_error = false, request_options: {})
|
||||
on_behalf_of ||= Account.representative
|
||||
|
||||
build_request(uri, on_behalf_of).perform do |response|
|
||||
build_request(uri, on_behalf_of, options: request_options).perform do |response|
|
||||
raise Mastodon::UnexpectedResponseError, response unless response_successful?(response) || response_error_unsalvageable?(response) || !raise_on_temporary_error
|
||||
|
||||
body_to_json(response.body_with_limit) if response.code == 200
|
||||
|
@ -204,8 +204,8 @@ module JsonLdHelper
|
|||
response.code == 501 || ((400...500).cover?(response.code) && ![401, 408, 429].include?(response.code))
|
||||
end
|
||||
|
||||
def build_request(uri, on_behalf_of = nil)
|
||||
Request.new(:get, uri).tap do |request|
|
||||
def build_request(uri, on_behalf_of = nil, options: {})
|
||||
Request.new(:get, uri, **options).tap do |request|
|
||||
request.on_behalf_of(on_behalf_of) if on_behalf_of
|
||||
request.add_headers('Accept' => 'application/activity+json, application/ld+json')
|
||||
end
|
||||
|
|
|
@ -170,6 +170,11 @@ export const openURL = routerHistory => (dispatch, getState) => {
|
|||
|
||||
export const clickSearchResult = (q, type) => (dispatch, getState) => {
|
||||
const previous = getState().getIn(['search', 'recent']);
|
||||
|
||||
if (previous.some(x => x.get('q') === q && x.get('type') === type)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const me = getState().getIn(['meta', 'me']);
|
||||
const current = previous.add(fromJS({ type, q })).takeLast(4);
|
||||
|
||||
|
@ -198,4 +203,4 @@ export const hydrateSearch = () => (dispatch, getState) => {
|
|||
if (history !== null) {
|
||||
dispatch(updateSearchHistory(history));
|
||||
}
|
||||
};
|
||||
};
|
||||
|
|
|
@ -63,14 +63,14 @@ class Search extends PureComponent {
|
|||
};
|
||||
|
||||
defaultOptions = [
|
||||
{ label: <><mark>has:</mark> <FormattedList type='disjunction' value={['media', 'poll', 'embed']} /></>, action: e => { e.preventDefault(); this._insertText('has:'); } },
|
||||
{ label: <><mark>is:</mark> <FormattedList type='disjunction' value={['reply', 'sensitive']} /></>, action: e => { e.preventDefault(); this._insertText('is:'); } },
|
||||
{ label: <><mark>language:</mark> <FormattedMessage id='search_popout.language_code' defaultMessage='ISO language code' /></>, action: e => { e.preventDefault(); this._insertText('language:'); } },
|
||||
{ label: <><mark>from:</mark> <FormattedMessage id='search_popout.user' defaultMessage='user' /></>, action: e => { e.preventDefault(); this._insertText('from:'); } },
|
||||
{ label: <><mark>before:</mark> <FormattedMessage id='search_popout.specific_date' defaultMessage='specific date' /></>, action: e => { e.preventDefault(); this._insertText('before:'); } },
|
||||
{ label: <><mark>during:</mark> <FormattedMessage id='search_popout.specific_date' defaultMessage='specific date' /></>, action: e => { e.preventDefault(); this._insertText('during:'); } },
|
||||
{ label: <><mark>after:</mark> <FormattedMessage id='search_popout.specific_date' defaultMessage='specific date' /></>, action: e => { e.preventDefault(); this._insertText('after:'); } },
|
||||
{ label: <><mark>in:</mark> <FormattedList type='disjunction' value={['all', 'library', 'public']} /></>, action: e => { e.preventDefault(); this._insertText('in:'); } }
|
||||
{ key: 'prompt-has', label: <><mark>has:</mark> <FormattedList type='disjunction' value={['media', 'poll', 'embed']} /></>, action: e => { e.preventDefault(); this._insertText('has:'); } },
|
||||
{ key: 'prompt-is', label: <><mark>is:</mark> <FormattedList type='disjunction' value={['reply', 'sensitive']} /></>, action: e => { e.preventDefault(); this._insertText('is:'); } },
|
||||
{ key: 'prompt-language', label: <><mark>language:</mark> <FormattedMessage id='search_popout.language_code' defaultMessage='ISO language code' /></>, action: e => { e.preventDefault(); this._insertText('language:'); } },
|
||||
{ key: 'prompt-from', label: <><mark>from:</mark> <FormattedMessage id='search_popout.user' defaultMessage='user' /></>, action: e => { e.preventDefault(); this._insertText('from:'); } },
|
||||
{ key: 'prompt-before', label: <><mark>before:</mark> <FormattedMessage id='search_popout.specific_date' defaultMessage='specific date' /></>, action: e => { e.preventDefault(); this._insertText('before:'); } },
|
||||
{ key: 'prompt-during', label: <><mark>during:</mark> <FormattedMessage id='search_popout.specific_date' defaultMessage='specific date' /></>, action: e => { e.preventDefault(); this._insertText('during:'); } },
|
||||
{ key: 'prompt-after', label: <><mark>after:</mark> <FormattedMessage id='search_popout.specific_date' defaultMessage='specific date' /></>, action: e => { e.preventDefault(); this._insertText('after:'); } },
|
||||
{ key: 'prompt-in', label: <><mark>in:</mark> <FormattedList type='disjunction' value={['all', 'library', 'public']} /></>, action: e => { e.preventDefault(); this._insertText('in:'); } }
|
||||
];
|
||||
|
||||
setRef = c => {
|
||||
|
@ -263,6 +263,8 @@ class Search extends PureComponent {
|
|||
const { recent } = this.props;
|
||||
|
||||
return recent.toArray().map(search => ({
|
||||
key: `${search.get('type')}/${search.get('q')}`,
|
||||
|
||||
label: labelForRecentSearch(search),
|
||||
|
||||
action: () => this.handleRecentSearchClick(search),
|
||||
|
@ -347,8 +349,8 @@ class Search extends PureComponent {
|
|||
<h4><FormattedMessage id='search_popout.recent' defaultMessage='Recent searches' /></h4>
|
||||
|
||||
<div className='search__popout__menu'>
|
||||
{recent.size > 0 ? this._getOptions().map(({ label, action, forget }, i) => (
|
||||
<button key={label} onMouseDown={action} className={classNames('search__popout__menu__item search__popout__menu__item--flex', { selected: selectedOption === i })}>
|
||||
{recent.size > 0 ? this._getOptions().map(({ label, key, action, forget }, i) => (
|
||||
<button key={key} onMouseDown={action} className={classNames('search__popout__menu__item search__popout__menu__item--flex', { selected: selectedOption === i })}>
|
||||
<span>{label}</span>
|
||||
<button className='icon-button' onMouseDown={forget}><Icon id='times' icon={CloseIcon} /></button>
|
||||
</button>
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
import { createAsyncThunk } from '@reduxjs/toolkit';
|
||||
import type { TypedUseSelectorHook } from 'react-redux';
|
||||
// eslint-disable-next-line @typescript-eslint/no-restricted-imports
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
|
||||
import type { AppDispatch, RootState } from './store';
|
||||
|
||||
export const useAppDispatch: () => AppDispatch = useDispatch;
|
||||
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector;
|
||||
export const useAppDispatch = useDispatch.withTypes<AppDispatch>();
|
||||
export const useAppSelector = useSelector.withTypes<RootState>();
|
||||
|
||||
export const createAppAsyncThunk = createAsyncThunk.withTypes<{
|
||||
state: RootState;
|
||||
|
|
|
@ -179,6 +179,11 @@ export const openURL = (value, history, onFailure) => (dispatch, getState) => {
|
|||
|
||||
export const clickSearchResult = (q, type) => (dispatch, getState) => {
|
||||
const previous = getState().getIn(['search', 'recent']);
|
||||
|
||||
if (previous.some(x => x.get('q') === q && x.get('type') === type)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const me = getState().getIn(['meta', 'me']);
|
||||
const current = previous.add(fromJS({ type, q })).takeLast(4);
|
||||
|
||||
|
@ -207,4 +212,4 @@ export const hydrateSearch = () => (dispatch, getState) => {
|
|||
if (history !== null) {
|
||||
dispatch(updateSearchHistory(history));
|
||||
}
|
||||
};
|
||||
};
|
||||
|
|
|
@ -62,14 +62,14 @@ class Search extends PureComponent {
|
|||
};
|
||||
|
||||
defaultOptions = [
|
||||
{ label: <><mark>has:</mark> <FormattedList type='disjunction' value={['media', 'poll', 'embed']} /></>, action: e => { e.preventDefault(); this._insertText('has:'); } },
|
||||
{ label: <><mark>is:</mark> <FormattedList type='disjunction' value={['reply', 'sensitive']} /></>, action: e => { e.preventDefault(); this._insertText('is:'); } },
|
||||
{ label: <><mark>language:</mark> <FormattedMessage id='search_popout.language_code' defaultMessage='ISO language code' /></>, action: e => { e.preventDefault(); this._insertText('language:'); } },
|
||||
{ label: <><mark>from:</mark> <FormattedMessage id='search_popout.user' defaultMessage='user' /></>, action: e => { e.preventDefault(); this._insertText('from:'); } },
|
||||
{ label: <><mark>before:</mark> <FormattedMessage id='search_popout.specific_date' defaultMessage='specific date' /></>, action: e => { e.preventDefault(); this._insertText('before:'); } },
|
||||
{ label: <><mark>during:</mark> <FormattedMessage id='search_popout.specific_date' defaultMessage='specific date' /></>, action: e => { e.preventDefault(); this._insertText('during:'); } },
|
||||
{ label: <><mark>after:</mark> <FormattedMessage id='search_popout.specific_date' defaultMessage='specific date' /></>, action: e => { e.preventDefault(); this._insertText('after:'); } },
|
||||
{ label: <><mark>in:</mark> <FormattedList type='disjunction' value={['all', 'library', 'public']} /></>, action: e => { e.preventDefault(); this._insertText('in:'); } }
|
||||
{ key: 'prompt-has', label: <><mark>has:</mark> <FormattedList type='disjunction' value={['media', 'poll', 'embed']} /></>, action: e => { e.preventDefault(); this._insertText('has:'); } },
|
||||
{ key: 'prompt-is', label: <><mark>is:</mark> <FormattedList type='disjunction' value={['reply', 'sensitive']} /></>, action: e => { e.preventDefault(); this._insertText('is:'); } },
|
||||
{ key: 'prompt-language', label: <><mark>language:</mark> <FormattedMessage id='search_popout.language_code' defaultMessage='ISO language code' /></>, action: e => { e.preventDefault(); this._insertText('language:'); } },
|
||||
{ key: 'prompt-from', label: <><mark>from:</mark> <FormattedMessage id='search_popout.user' defaultMessage='user' /></>, action: e => { e.preventDefault(); this._insertText('from:'); } },
|
||||
{ key: 'prompt-before', label: <><mark>before:</mark> <FormattedMessage id='search_popout.specific_date' defaultMessage='specific date' /></>, action: e => { e.preventDefault(); this._insertText('before:'); } },
|
||||
{ key: 'prompt-during', label: <><mark>during:</mark> <FormattedMessage id='search_popout.specific_date' defaultMessage='specific date' /></>, action: e => { e.preventDefault(); this._insertText('during:'); } },
|
||||
{ key: 'prompt-after', label: <><mark>after:</mark> <FormattedMessage id='search_popout.specific_date' defaultMessage='specific date' /></>, action: e => { e.preventDefault(); this._insertText('after:'); } },
|
||||
{ key: 'prompt-in', label: <><mark>in:</mark> <FormattedList type='disjunction' value={['all', 'library', 'public']} /></>, action: e => { e.preventDefault(); this._insertText('in:'); } }
|
||||
];
|
||||
|
||||
setRef = c => {
|
||||
|
@ -262,6 +262,8 @@ class Search extends PureComponent {
|
|||
const { recent } = this.props;
|
||||
|
||||
return recent.toArray().map(search => ({
|
||||
key: `${search.get('type')}/${search.get('q')}`,
|
||||
|
||||
label: labelForRecentSearch(search),
|
||||
|
||||
action: () => this.handleRecentSearchClick(search),
|
||||
|
@ -346,8 +348,8 @@ class Search extends PureComponent {
|
|||
<h4><FormattedMessage id='search_popout.recent' defaultMessage='Recent searches' /></h4>
|
||||
|
||||
<div className='search__popout__menu'>
|
||||
{recent.size > 0 ? this._getOptions().map(({ label, action, forget }, i) => (
|
||||
<button key={label} onMouseDown={action} className={classNames('search__popout__menu__item search__popout__menu__item--flex', { selected: selectedOption === i })}>
|
||||
{recent.size > 0 ? this._getOptions().map(({ label, key, action, forget }, i) => (
|
||||
<button key={key} onMouseDown={action} className={classNames('search__popout__menu__item search__popout__menu__item--flex', { selected: selectedOption === i })}>
|
||||
<span>{label}</span>
|
||||
<button className='icon-button' onMouseDown={forget}><Icon id='times' icon={CloseIcon} /></button>
|
||||
</button>
|
||||
|
|
|
@ -116,7 +116,6 @@
|
|||
"compose_form.publish_form": "Artículu nuevu",
|
||||
"compose_form.publish_loud": "¡{publish}!",
|
||||
"compose_form.save_changes": "Guardar los cambeos",
|
||||
"compose_form.spoiler.unmarked": "Text is not hidden",
|
||||
"confirmation_modal.cancel": "Encaboxar",
|
||||
"confirmations.block.block_and_report": "Bloquiar ya informar",
|
||||
"confirmations.block.confirm": "Bloquiar",
|
||||
|
@ -146,6 +145,7 @@
|
|||
"dismissable_banner.community_timeline": "Esta seición contién los artículos públicos más actuales de los perfiles agospiaos nel dominiu {domain}.",
|
||||
"dismissable_banner.dismiss": "Escartar",
|
||||
"dismissable_banner.explore_tags": "Esta seición contién les etiquetes del fediversu que tán ganando popularidá güei. Les etiquetes más usaes polos perfiles apaecen no cimero.",
|
||||
"dismissable_banner.public_timeline": "Esta seición contién los artículos más nuevos de les persones na web social que les persones de {domain} siguen.",
|
||||
"embed.instructions": "Empotra esti artículu nel to sitiu web pente la copia del códigu d'abaxo.",
|
||||
"embed.preview": "Va apaecer asina:",
|
||||
"emoji_button.activity": "Actividá",
|
||||
|
@ -155,6 +155,7 @@
|
|||
"emoji_button.not_found": "Nun s'atoparon fustaxes que concasen",
|
||||
"emoji_button.objects": "Oxetos",
|
||||
"emoji_button.people": "Persones",
|
||||
"emoji_button.recent": "D'usu frecuente",
|
||||
"emoji_button.search": "Buscar…",
|
||||
"emoji_button.search_results": "Resultaos de la busca",
|
||||
"emoji_button.symbols": "Símbolos",
|
||||
|
@ -217,7 +218,6 @@
|
|||
"hashtag.column_header.tag_mode.any": "o {additional}",
|
||||
"hashtag.column_header.tag_mode.none": "ensin {additional}",
|
||||
"hashtag.column_settings.select.no_options_message": "Nun s'atopó nenguna suxerencia",
|
||||
"hashtag.column_settings.tag_toggle": "Include additional tags in this column",
|
||||
"hashtag.counter_by_accounts": "{count, plural, one {{counter} participante} other {{counter} participantes}}",
|
||||
"hashtag.follow": "Siguir a la etiqueta",
|
||||
"hashtag.unfollow": "Dexar de siguir a la etiqueta",
|
||||
|
@ -259,7 +259,6 @@
|
|||
"keyboard_shortcuts.reply": "Responder a un artículu",
|
||||
"keyboard_shortcuts.requests": "Abrir la llista de solicitúes de siguimientu",
|
||||
"keyboard_shortcuts.search": "Enfocar la barra de busca",
|
||||
"keyboard_shortcuts.spoilers": "to show/hide CW field",
|
||||
"keyboard_shortcuts.start": "Abrir la columna «Entamar»",
|
||||
"keyboard_shortcuts.toggle_sensitivity": "Amosar/anubrir el conteníu multimedia",
|
||||
"keyboard_shortcuts.toot": "Comenzar un artículu nuevu",
|
||||
|
@ -412,12 +411,16 @@
|
|||
"search.quick_action.go_to_hashtag": "Dir a la etiqueta {x}",
|
||||
"search.quick_action.status_search": "Artículos que concasen con {x}",
|
||||
"search.search_or_paste": "Busca o apiega una URL",
|
||||
"search_popout.language_code": "códigu de llingua ISO",
|
||||
"search_popout.quick_actions": "Aiciones rápides",
|
||||
"search_popout.recent": "Busques de recién",
|
||||
"search_popout.specific_date": "data específica",
|
||||
"search_popout.user": "perfil",
|
||||
"search_results.accounts": "Perfiles",
|
||||
"search_results.all": "Too",
|
||||
"search_results.hashtags": "Etiquetes",
|
||||
"search_results.nothing_found": "Nun se pudo atopar nada con esos términos de busca",
|
||||
"search_results.see_all": "Ver too",
|
||||
"search_results.statuses": "Artículos",
|
||||
"search_results.title": "Busca de: {q}",
|
||||
"server_banner.introduction": "{domain} ye parte de la rede social descentralizada que tien la teunoloxía de {mastodon}.",
|
||||
|
@ -460,6 +463,7 @@
|
|||
"status.replied_to": "En rempuesta a {name}",
|
||||
"status.reply": "Responder",
|
||||
"status.replyAll": "Responder al filu",
|
||||
"status.report": "Informar de @{name}",
|
||||
"status.sensitive_warning": "Conteníu sensible",
|
||||
"status.show_filter_reason": "Amosar de toes toes",
|
||||
"status.show_less": "Amosar menos",
|
||||
|
|
|
@ -683,7 +683,7 @@
|
|||
"status.show_more": "펼치기",
|
||||
"status.show_more_all": "모두 펼치기",
|
||||
"status.show_original": "원본 보기",
|
||||
"status.title.with_attachments": "{user} 님이 {attachmentCount, plural, one {첨부} other {{attachmentCount}개 첨부}}하여 게시",
|
||||
"status.title.with_attachments": "{user} 님이 {attachmentCount, plural, one {첨부파일} other {{attachmentCount}개의 첨부파일}}과 함께 게시함",
|
||||
"status.translate": "번역",
|
||||
"status.translated_from_with": "{provider}에 의해 {lang}에서 번역됨",
|
||||
"status.uncached_media_warning": "마리보기 허용되지 않음",
|
||||
|
|
|
@ -328,6 +328,7 @@
|
|||
"interaction_modal.on_another_server": "En otro sirvidor",
|
||||
"interaction_modal.on_this_server": "En este sirvidor",
|
||||
"interaction_modal.sign_in": "No estas konektado kon este sirvidor. Ande tyenes tu kuento?",
|
||||
"interaction_modal.sign_in_hint": "Konsejo: Akel es el sitio adonde te enrejistrates. Si no lo akodras, bushka el mesaj de posta elektronika de bienvenida en tu kuti de arivo. Tambien puedes eskrivir tu nombre de utilizador kompleto (por enshemplo @Mastodon@mastodon.social)",
|
||||
"interaction_modal.title.favourite": "Endika ke te plaze publikasyon de {name}",
|
||||
"interaction_modal.title.follow": "Sige a {name}",
|
||||
"interaction_modal.title.reblog": "Repartaja publikasyon de {name}",
|
||||
|
@ -478,6 +479,7 @@
|
|||
"onboarding.actions.go_to_explore": "Va a los trendes",
|
||||
"onboarding.actions.go_to_home": "Va a tu linya prinsipala",
|
||||
"onboarding.compose.template": "Ke haber, #Mastodon?",
|
||||
"onboarding.follows.empty": "Malorozamente, no se pueden amostrar rezultados en este momento. Puedes aprovar uzar la bushkeda o navigar por la pajina de eksplorasyon para topar personas a las que segir, o aprovarlo de muevo mas tadre.",
|
||||
"onboarding.follows.title": "Personaliza tu linya prinsipala",
|
||||
"onboarding.profile.discoverable": "Faz ke mi profil apareska en bushkedas",
|
||||
"onboarding.profile.display_name": "Nombre amostrado",
|
||||
|
@ -497,7 +499,9 @@
|
|||
"onboarding.start.title": "Lo logrates!",
|
||||
"onboarding.steps.follow_people.body": "El buto de Mastodon es segir a djente interesante.",
|
||||
"onboarding.steps.follow_people.title": "Personaliza tu linya prinsipala",
|
||||
"onboarding.steps.publish_status.body": "Puedes introdusirte al mundo con teksto, fotos, videos o anketas {emoji}",
|
||||
"onboarding.steps.publish_status.title": "Eskrive tu primera publikasyon",
|
||||
"onboarding.steps.setup_profile.body": "Kompleta tu profil para aumentar tus enteraksyones.",
|
||||
"onboarding.steps.setup_profile.title": "Personaliza tu profil",
|
||||
"onboarding.steps.share_profile.body": "Informe a tus amigos komo toparte en Mastodon",
|
||||
"onboarding.steps.share_profile.title": "Partaja tu profil de Mastodon",
|
||||
|
|
|
@ -314,7 +314,7 @@
|
|||
"home.explore_prompt.body": "ฟีดหน้าแรกของคุณจะมีการผสมผสานของโพสต์จากแฮชแท็กที่คุณได้เลือกติดตาม, ผู้คนที่คุณได้เลือกติดตาม และโพสต์ที่เขาดัน หากนั่นรู้สึกเงียบเกินไป คุณอาจต้องการ:",
|
||||
"home.explore_prompt.title": "นี่คือฐานหน้าแรกของคุณภายใน Mastodon",
|
||||
"home.hide_announcements": "ซ่อนประกาศ",
|
||||
"home.pending_critical_update.body": "โปรดอัปเดตเซิร์ฟเวอร์ Mastodon ของคุณโดยเร็วที่สุดเท่าที่จะทำได้!",
|
||||
"home.pending_critical_update.body": "โปรดอัปเดตเซิร์ฟเวอร์ Mastodon ของคุณโดยเร็วที่สุดเท่าที่จะเป็นไปได้!",
|
||||
"home.pending_critical_update.link": "ดูการอัปเดต",
|
||||
"home.pending_critical_update.title": "มีการอัปเดตความปลอดภัยสำคัญพร้อมใช้งาน!",
|
||||
"home.show_announcements": "แสดงประกาศ",
|
||||
|
|
|
@ -358,7 +358,7 @@
|
|||
"keyboard_shortcuts.my_profile": "mở hồ sơ của bạn",
|
||||
"keyboard_shortcuts.notifications": "mở thông báo",
|
||||
"keyboard_shortcuts.open_media": "mở ảnh hoặc video",
|
||||
"keyboard_shortcuts.pinned": "mở những tút đã ghim",
|
||||
"keyboard_shortcuts.pinned": "Open pinned posts list",
|
||||
"keyboard_shortcuts.profile": "mở trang của người đăng tút",
|
||||
"keyboard_shortcuts.reply": "trả lời",
|
||||
"keyboard_shortcuts.requests": "mở danh sách yêu cầu theo dõi",
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
import { createAsyncThunk } from '@reduxjs/toolkit';
|
||||
import type { TypedUseSelectorHook } from 'react-redux';
|
||||
// eslint-disable-next-line @typescript-eslint/no-restricted-imports
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
|
||||
import type { AppDispatch, RootState } from './store';
|
||||
|
||||
export const useAppDispatch: () => AppDispatch = useDispatch;
|
||||
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector;
|
||||
export const useAppDispatch = useDispatch.withTypes<AppDispatch>();
|
||||
export const useAppSelector = useSelector.withTypes<RootState>();
|
||||
|
||||
export const createAppAsyncThunk = createAsyncThunk.withTypes<{
|
||||
state: RootState;
|
||||
|
|
|
@ -100,9 +100,8 @@ table + p {
|
|||
border-top-right-radius: 12px;
|
||||
height: 140px;
|
||||
vertical-align: bottom;
|
||||
background-color: #f3f2f5;
|
||||
background-position: center;
|
||||
background-size: cover;
|
||||
background-position: center !important;
|
||||
background-size: cover !important;
|
||||
}
|
||||
|
||||
.email-account-banner-inner-td {
|
||||
|
|
|
@ -26,11 +26,11 @@ class StatusCacheHydrator
|
|||
|
||||
def hydrate_non_reblog_payload(empty_payload, account_id)
|
||||
empty_payload.tap do |payload|
|
||||
payload[:favourited] = Favourite.where(account_id: account_id, status_id: @status.id).exists?
|
||||
payload[:reblogged] = Status.where(account_id: account_id, reblog_of_id: @status.id).exists?
|
||||
payload[:muted] = ConversationMute.where(account_id: account_id, conversation_id: @status.conversation_id).exists?
|
||||
payload[:bookmarked] = Bookmark.where(account_id: account_id, status_id: @status.id).exists?
|
||||
payload[:pinned] = StatusPin.where(account_id: account_id, status_id: @status.id).exists? if @status.account_id == account_id
|
||||
payload[:favourited] = Favourite.exists?(account_id: account_id, status_id: @status.id)
|
||||
payload[:reblogged] = Status.exists?(account_id: account_id, reblog_of_id: @status.id)
|
||||
payload[:muted] = ConversationMute.exists?(account_id: account_id, conversation_id: @status.conversation_id)
|
||||
payload[:bookmarked] = Bookmark.exists?(account_id: account_id, status_id: @status.id)
|
||||
payload[:pinned] = StatusPin.exists?(account_id: account_id, status_id: @status.id) if @status.account_id == account_id
|
||||
payload[:filtered] = mapped_applied_custom_filter(account_id, @status)
|
||||
|
||||
if payload[:poll]
|
||||
|
@ -51,11 +51,11 @@ class StatusCacheHydrator
|
|||
# used to create the status, we need to hydrate it here too
|
||||
payload[:reblog][:application] = payload_reblog_application if payload[:reblog][:application].nil? && @status.reblog.account_id == account_id
|
||||
|
||||
payload[:reblog][:favourited] = Favourite.where(account_id: account_id, status_id: @status.reblog_of_id).exists?
|
||||
payload[:reblog][:reblogged] = Status.where(account_id: account_id, reblog_of_id: @status.reblog_of_id).exists?
|
||||
payload[:reblog][:muted] = ConversationMute.where(account_id: account_id, conversation_id: @status.reblog.conversation_id).exists?
|
||||
payload[:reblog][:bookmarked] = Bookmark.where(account_id: account_id, status_id: @status.reblog_of_id).exists?
|
||||
payload[:reblog][:pinned] = StatusPin.where(account_id: account_id, status_id: @status.reblog_of_id).exists? if @status.reblog.account_id == account_id
|
||||
payload[:reblog][:favourited] = Favourite.exists?(account_id: account_id, status_id: @status.reblog_of_id)
|
||||
payload[:reblog][:reblogged] = Status.exists?(account_id: account_id, reblog_of_id: @status.reblog_of_id)
|
||||
payload[:reblog][:muted] = ConversationMute.exists?(account_id: account_id, conversation_id: @status.reblog.conversation_id)
|
||||
payload[:reblog][:bookmarked] = Bookmark.exists?(account_id: account_id, status_id: @status.reblog_of_id)
|
||||
payload[:reblog][:pinned] = StatusPin.exists?(account_id: account_id, status_id: @status.reblog_of_id) if @status.reblog.account_id == account_id
|
||||
payload[:reblog][:filtered] = payload[:filtered]
|
||||
|
||||
if payload[:reblog][:poll]
|
||||
|
|
|
@ -191,6 +191,18 @@ class UserMailer < Devise::Mailer
|
|||
end
|
||||
end
|
||||
|
||||
def failed_2fa(user, remote_ip, user_agent, timestamp)
|
||||
@resource = user
|
||||
@remote_ip = remote_ip
|
||||
@user_agent = user_agent
|
||||
@detection = Browser.new(user_agent)
|
||||
@timestamp = timestamp.to_time.utc
|
||||
|
||||
I18n.with_locale(locale) do
|
||||
mail subject: default_i18n_subject
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def default_devise_subject
|
||||
|
|
|
@ -127,9 +127,11 @@ class Account < ApplicationRecord
|
|||
scope :bots, -> { where(actor_type: %w(Application Service)) }
|
||||
scope :groups, -> { where(actor_type: 'Group') }
|
||||
scope :alphabetic, -> { order(domain: :asc, username: :asc) }
|
||||
scope :matches_uri_prefix, ->(value) { where(arel_table[:uri].matches("#{sanitize_sql_like(value)}/%", false, true)).or(where(uri: value)) }
|
||||
scope :matches_username, ->(value) { where('lower((username)::text) LIKE lower(?)', "#{value}%") }
|
||||
scope :matches_display_name, ->(value) { where(arel_table[:display_name].matches("#{value}%")) }
|
||||
scope :without_unapproved, -> { left_outer_joins(:user).merge(User.approved.confirmed).or(remote) }
|
||||
scope :auditable, -> { where(id: Admin::ActionLog.select(:account_id).distinct) }
|
||||
scope :searchable, -> { without_unapproved.without_suspended.where(moved_to_account_id: nil) }
|
||||
scope :discoverable, -> { searchable.without_silenced.where(discoverable: true).joins(:account_stat) }
|
||||
scope :by_recent_status, -> { includes(:account_stat).merge(AccountStat.order('last_status_at DESC NULLS LAST')).references(:account_stat) }
|
||||
|
|
|
@ -72,7 +72,7 @@ class Admin::ActionLogFilter
|
|||
end
|
||||
|
||||
def results
|
||||
scope = latest_action_logs.includes(:target)
|
||||
scope = latest_action_logs.includes(:target, :account)
|
||||
|
||||
params.each do |key, value|
|
||||
next if key.to_s == 'page'
|
||||
|
|
|
@ -1,66 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class PrivacyPolicy < ActiveModelSerializers::Model
|
||||
DEFAULT_PRIVACY_POLICY = <<~TXT
|
||||
This privacy policy describes how %{domain} ("%{domain}", "we", "us") collects, protects and uses the personally identifiable information you may provide through the %{domain} website or its API. The policy also describes the choices available to you regarding our use of your personal information and how you can access and update this information. This policy does not apply to the practices of companies that %{domain} does not own or control, or to individuals that %{domain} does not employ or manage.
|
||||
|
||||
# What information do we collect?
|
||||
|
||||
- **Basic account information**: If you register on this server, you may be asked to enter a username, an e-mail address and a password. You may also enter additional profile information such as a display name and biography, and upload a profile picture and header image. The username, display name, biography, profile picture and header image are always listed publicly.
|
||||
- **Posts, following and other public information**: The list of people you follow is listed publicly, the same is true for your followers. When you submit a message, the date and time is stored as well as the application you submitted the message from. Messages may contain media attachments, such as pictures and videos. Public and unlisted posts are available publicly. When you feature a post on your profile, that is also publicly available information. Your posts are delivered to your followers, in some cases it means they are delivered to different servers and copies are stored there. When you delete posts, this is likewise delivered to your followers. The action of reblogging or favouriting another post is always public.
|
||||
- **Direct and followers-only posts**: All posts are stored and processed on the server. Followers-only posts are delivered to your followers and users who are mentioned in them, and direct posts are delivered only to users mentioned in them. In some cases it means they are delivered to different servers and copies are stored there. We make a good faith effort to limit the access to those posts only to authorized persons, but other servers may fail to do so. Therefore it's important to review servers your followers belong to. You may toggle an option to approve and reject new followers manually in the settings. **Please keep in mind that the operators of the server and any receiving server may view such messages**, and that recipients may screenshot, copy or otherwise re-share them. **Do not share any sensitive information over Mastodon.**
|
||||
- **IPs and other metadata**: When you log in, we record the IP address you log in from, as well as the name of your browser application. All the logged in sessions are available for your review and revocation in the settings. The latest IP address used is stored for up to 12 months. We also may retain server logs which include the IP address of every request to our server.
|
||||
|
||||
# What do we use your information for?
|
||||
|
||||
Any of the information we collect from you may be used in the following ways:
|
||||
|
||||
- To provide the core functionality of Mastodon. You can only interact with other people's content and post your own content when you are logged in. For example, you may follow other people to view their combined posts in your own personalized home timeline.
|
||||
- To aid moderation of the community, for example comparing your IP address with other known ones to determine ban evasion or other violations.
|
||||
- The email address you provide may be used to send you information, notifications about other people interacting with your content or sending you messages, and to respond to inquiries, and/or other requests or questions.
|
||||
|
||||
# How do we protect your information?
|
||||
|
||||
We implement a variety of security measures to maintain the safety of your personal information when you enter, submit, or access your personal information. Among other things, your browser session, as well as the traffic between your applications and the API, are secured with SSL, and your password is hashed using a strong one-way algorithm. You may enable two-factor authentication to further secure access to your account.
|
||||
|
||||
# What is our data retention policy?
|
||||
|
||||
We will make a good faith effort to:
|
||||
|
||||
- Retain server logs containing the IP address of all requests to this server, in so far as such logs are kept, no more than 90 days.
|
||||
- Retain the IP addresses associated with registered users no more than 12 months.
|
||||
|
||||
You can request and download an archive of your content, including your posts, media attachments, profile picture, and header image.
|
||||
|
||||
You may irreversibly delete your account at any time.
|
||||
|
||||
# Do we use cookies?
|
||||
|
||||
Yes. Cookies are small files that a site or its service provider transfers to your computer's hard drive through your Web browser (if you allow). These cookies enable the site to recognize your browser and, if you have a registered account, associate it with your registered account.
|
||||
|
||||
We use cookies to understand and save your preferences for future visits.
|
||||
|
||||
# Do we disclose any information to outside parties?
|
||||
|
||||
We do not sell, trade, or otherwise transfer to outside parties your personally identifiable information. This does not include trusted third parties who assist us in operating our site, conducting our business, or servicing you, so long as those parties agree to keep this information confidential. We may also release your information when we believe release is appropriate to comply with the law, enforce our site policies, or protect ours or others rights, property, or safety.
|
||||
|
||||
Your public content may be downloaded by other servers in the network. Your public and followers-only posts are delivered to the servers where your followers reside, and direct messages are delivered to the servers of the recipients, in so far as those followers or recipients reside on a different server than this.
|
||||
|
||||
When you authorize an application to use your account, depending on the scope of permissions you approve, it may access your public profile information, your following list, your followers, your lists, all your posts, and your favourites. Applications can never access your e-mail address or password.
|
||||
|
||||
# Site usage by children
|
||||
|
||||
If this server is in the EU or the EEA: Our site, products and services are all directed to people who are at least 16 years old. If you are under the age of 16, per the requirements of the GDPR (General Data Protection Regulation) do not use this site.
|
||||
|
||||
If this server is in the USA: Our site, products and services are all directed to people who are at least 13 years old. If you are under the age of 13, per the requirements of COPPA (Children's Online Privacy Protection Act) do not use this site.
|
||||
|
||||
Law requirements can be different if this server is in another jurisdiction.
|
||||
|
||||
___
|
||||
|
||||
This document is CC-BY-SA. Originally adapted from the [Discourse privacy policy](https://github.com/discourse/discourse).
|
||||
TXT
|
||||
|
||||
DEFAULT_PRIVACY_POLICY = Rails.root.join('config', 'templates', 'privacy-policy.md').read
|
||||
DEFAULT_UPDATED_AT = DateTime.new(2022, 10, 7).freeze
|
||||
|
||||
attributes :updated_at, :text
|
||||
|
|
|
@ -19,7 +19,7 @@ class REST::TagSerializer < ActiveModel::Serializer
|
|||
if instance_options && instance_options[:relationships]
|
||||
instance_options[:relationships].following_map[object.id] || false
|
||||
else
|
||||
TagFollow.where(tag_id: object.id, account_id: current_user.account_id).exists?
|
||||
TagFollow.exists?(tag_id: object.id, account_id: current_user.account_id)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -23,9 +23,9 @@ class ActivityPub::FetchFeaturedCollectionService < BaseService
|
|||
|
||||
case collection['type']
|
||||
when 'Collection', 'CollectionPage'
|
||||
collection['items']
|
||||
as_array(collection['items'])
|
||||
when 'OrderedCollection', 'OrderedCollectionPage'
|
||||
collection['orderedItems']
|
||||
as_array(collection['orderedItems'])
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -26,9 +26,9 @@ class ActivityPub::FetchRepliesService < BaseService
|
|||
|
||||
case collection['type']
|
||||
when 'Collection', 'CollectionPage'
|
||||
collection['items']
|
||||
as_array(collection['items'])
|
||||
when 'OrderedCollection', 'OrderedCollectionPage'
|
||||
collection['orderedItems']
|
||||
as_array(collection['orderedItems'])
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -37,7 +37,20 @@ class ActivityPub::FetchRepliesService < BaseService
|
|||
return unless @allow_synchronous_requests
|
||||
return if non_matching_uri_hosts?(@account.uri, collection_or_uri)
|
||||
|
||||
fetch_resource_without_id_validation(collection_or_uri, nil, true)
|
||||
# NOTE: For backward compatibility reasons, Mastodon signs outgoing
|
||||
# queries incorrectly by default.
|
||||
#
|
||||
# While this is relevant for all URLs with query strings, this is
|
||||
# the only code path where this happens in practice.
|
||||
#
|
||||
# Therefore, retry with correct signatures if this fails.
|
||||
begin
|
||||
fetch_resource_without_id_validation(collection_or_uri, nil, true)
|
||||
rescue Mastodon::UnexpectedResponseError => e
|
||||
raise unless e.response && e.response.code == 401 && Addressable::URI.parse(collection_or_uri).query.present?
|
||||
|
||||
fetch_resource_without_id_validation(collection_or_uri, nil, true, request_options: { with_query_string: true })
|
||||
end
|
||||
end
|
||||
|
||||
def filtered_replies
|
||||
|
|
|
@ -59,9 +59,9 @@ class ActivityPub::SynchronizeFollowersService < BaseService
|
|||
|
||||
case collection['type']
|
||||
when 'Collection', 'CollectionPage'
|
||||
collection['items']
|
||||
as_array(collection['items'])
|
||||
when 'OrderedCollection', 'OrderedCollectionPage'
|
||||
collection['orderedItems']
|
||||
as_array(collection['orderedItems'])
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -69,7 +69,7 @@ class Keys::QueryService < BaseService
|
|||
|
||||
return if json['items'].blank?
|
||||
|
||||
@devices = json['items'].map do |device|
|
||||
@devices = as_array(json['items']).map do |device|
|
||||
Device.new(device_id: device['id'], name: device['name'], identity_key: device.dig('identityKey', 'publicKeyBase64'), fingerprint_key: device.dig('fingerprintKey', 'publicKeyBase64'), claim_url: device['claim'])
|
||||
end
|
||||
rescue HTTP::Error, OpenSSL::SSL::SSLError, Mastodon::Error => e
|
||||
|
|
24
app/views/user_mailer/failed_2fa.html.haml
Normal file
24
app/views/user_mailer/failed_2fa.html.haml
Normal file
|
@ -0,0 +1,24 @@
|
|||
= content_for :heading do
|
||||
= render 'application/mailer/heading', heading_title: t('user_mailer.failed_2fa.title'), heading_subtitle: t('user_mailer.failed_2fa.explanation'), heading_image_url: frontend_asset_url('images/mailer-new/heading/login.png')
|
||||
%table.email-w-full{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
|
||||
%tr
|
||||
%td.email-body-padding-td
|
||||
%table.email-inner-card-table{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' }
|
||||
%tr
|
||||
%td.email-inner-card-td.email-prose
|
||||
%p= t 'user_mailer.failed_2fa.details'
|
||||
%p
|
||||
%strong #{t('sessions.ip')}:
|
||||
= @remote_ip
|
||||
%br/
|
||||
%strong #{t('sessions.browser')}:
|
||||
%span{ title: @user_agent }
|
||||
= t 'sessions.description',
|
||||
browser: t("sessions.browsers.#{@detection.id}", default: @detection.id.to_s),
|
||||
platform: t("sessions.platforms.#{@detection.platform.id}", default: @detection.platform.id.to_s)
|
||||
%br/
|
||||
%strong #{t('sessions.date')}:
|
||||
= l(@timestamp.in_time_zone(@resource.time_zone.presence), format: :with_time_zone)
|
||||
= render 'application/mailer/button', text: t('settings.account_settings'), url: edit_user_registration_url
|
||||
%p= t 'user_mailer.failed_2fa.further_actions_html',
|
||||
action: link_to(t('user_mailer.suspicious_sign_in.change_password'), edit_user_registration_url)
|
15
app/views/user_mailer/failed_2fa.text.erb
Normal file
15
app/views/user_mailer/failed_2fa.text.erb
Normal file
|
@ -0,0 +1,15 @@
|
|||
<%= t 'user_mailer.failed_2fa.title' %>
|
||||
|
||||
===
|
||||
|
||||
<%= t 'user_mailer.failed_2fa.explanation' %>
|
||||
|
||||
<%= t 'user_mailer.failed_2fa.details' %>
|
||||
|
||||
<%= t('sessions.ip') %>: <%= @remote_ip %>
|
||||
<%= t('sessions.browser') %>: <%= t('sessions.description', browser: t("sessions.browsers.#{@detection.id}", default: "#{@detection.id}"), platform: t("sessions.platforms.#{@detection.platform.id}", default: "#{@detection.platform.id}")) %>
|
||||
<%= l(@timestamp.in_time_zone(@resource.time_zone.presence), format: :with_time_zone) %>
|
||||
|
||||
<%= t 'user_mailer.failed_2fa.further_actions_html', action: t('user_mailer.suspicious_sign_in.change_password') %>
|
||||
|
||||
=> <%= edit_user_registration_url %>
|
|
@ -909,6 +909,7 @@ ast:
|
|||
users:
|
||||
follow_limit_reached: Nun pues siguir a más de %{limit} persones
|
||||
invalid_otp_token: El códigu de l'autenticación en dos pasos nun ye válidu
|
||||
rate_limited: Fixéronse milenta intentos d'autenticación. Volvi tentalo dempués.
|
||||
seamless_external_login: Aniciesti la sesión pente un serviciu esternu, polo que la configuración de la contraseña ya de la direición de corréu electrónicu nun tán disponibles.
|
||||
signed_in_as: 'Aniciesti la sesión como:'
|
||||
verification:
|
||||
|
|
|
@ -1843,6 +1843,7 @@ bg:
|
|||
go_to_sso_account_settings: Отидете при настройките на акаунта на своя доставчик на идентичност
|
||||
invalid_otp_token: Невалиден код
|
||||
otp_lost_help_html: Ако загубите достъп до двете, то може да се свържете с %{email}
|
||||
rate_limited: Премного опити за удостоверяване. Опитайте пак по-късно.
|
||||
seamless_external_login: Влезли сте чрез външна услуга, така че настройките за парола и имейл не са налични.
|
||||
signed_in_as: 'Влезли като:'
|
||||
verification:
|
||||
|
|
|
@ -1840,6 +1840,7 @@ ca:
|
|||
go_to_sso_account_settings: Ves a la configuració del compte del teu proveïdor d'identitat
|
||||
invalid_otp_token: El codi de dos factors no és correcte
|
||||
otp_lost_help_html: Si has perdut l'accés a tots dos pots contactar per %{email}
|
||||
rate_limited: Excessius intents d'autenticació, torneu-ho a provar més tard.
|
||||
seamless_external_login: Has iniciat sessió via un servei extern per tant els ajustos de contrasenya i correu electrònic no estan disponibles.
|
||||
signed_in_as: 'Sessió iniciada com a:'
|
||||
verification:
|
||||
|
|
|
@ -1843,6 +1843,7 @@ da:
|
|||
go_to_sso_account_settings: Gå til identitetsudbyderens kontoindstillinger
|
||||
invalid_otp_token: Ugyldig tofaktorkode
|
||||
otp_lost_help_html: Har du mistet adgang til begge, kan du kontakte %{email}
|
||||
rate_limited: For mange godkendelsesforsøg. Prøv igen senere.
|
||||
seamless_external_login: Du er logget ind via en ekstern tjeneste, så adgangskode- og e-mailindstillinger er utilgængelige.
|
||||
signed_in_as: 'Logget ind som:'
|
||||
verification:
|
||||
|
|
|
@ -1843,6 +1843,7 @@ de:
|
|||
go_to_sso_account_settings: Kontoeinstellungen des Identitätsanbieters aufrufen
|
||||
invalid_otp_token: Ungültiger Code der Zwei-Faktor-Authentisierung (2FA)
|
||||
otp_lost_help_html: Wenn du beides nicht mehr weißt, melde dich bitte bei uns unter der E-Mail-Adresse %{email}
|
||||
rate_limited: Zu viele Authentisierungsversuche. Bitte versuche es später noch einmal.
|
||||
seamless_external_login: Du bist über einen externen Dienst angemeldet, daher sind Passwort- und E-Mail-Einstellungen nicht verfügbar.
|
||||
signed_in_as: 'Angemeldet als:'
|
||||
verification:
|
||||
|
|
|
@ -47,14 +47,19 @@ fi:
|
|||
subject: 'Mastodon: ohjeet salasanan vaihtoon'
|
||||
title: Salasanan vaihto
|
||||
two_factor_disabled:
|
||||
explanation: Sisäänkirjautuminen on nyt mahdollista pelkällä sähköpostiosoitteella ja salasanalla.
|
||||
subject: 'Mastodon: kaksivaiheinen todennus poistettu käytöstä'
|
||||
subtitle: Kaksivaiheinen todennus on poistettu käytöstä tililtäsi.
|
||||
title: 2-vaiheinen todennus pois käytöstä
|
||||
two_factor_enabled:
|
||||
explanation: Sisäänkirjautuminen edellyttää liitetyn TOTP-sovelluksen luomaa aikarajattua kertatunnuslukua.
|
||||
subject: 'Mastodon: kaksivaiheinen todennus otettu käyttöön'
|
||||
subtitle: Kaksivaiheinen todennus on otettu käyttöön tilillesi.
|
||||
title: 2-vaiheinen todennus käytössä
|
||||
two_factor_recovery_codes_changed:
|
||||
explanation: Uudet palautuskoodit on nyt luotu ja vanhat on mitätöity.
|
||||
subject: 'Mastodon: kaksivaiheisen todennuksen palautuskoodit luotiin uudelleen'
|
||||
subtitle: Aiemmat palautuskoodit on mitätöity ja tilalle on luotu uudet.
|
||||
title: 2-vaiheisen todennuksen palautuskoodit vaihdettiin
|
||||
unlock_instructions:
|
||||
subject: 'Mastodon: lukituksen poistamisen ohjeet'
|
||||
|
@ -68,9 +73,13 @@ fi:
|
|||
subject: 'Mastodon: suojausavain poistettu'
|
||||
title: Yksi suojausavaimistasi on poistettu
|
||||
webauthn_disabled:
|
||||
explanation: Turva-avaimin kirjautuminen on poistettu käytöstä tililtäsi.
|
||||
extra: Sisäänkirjautuminen on nyt mahdollista pelkällä palveluun liitetyn TOTP-sovelluksen luomalla aikarajoitteisella kertatunnusluvulla.
|
||||
subject: 'Mastodon: Todennus suojausavaimilla poistettu käytöstä'
|
||||
title: Suojausavaimet poistettu käytöstä
|
||||
webauthn_enabled:
|
||||
explanation: Turva-avaimella kirjautuminen on otettu käyttöön tilillesi.
|
||||
extra: Voit nyt kirjautua sisään turva-avaimellasi.
|
||||
subject: 'Mastodon: Todennus suojausavaimella on otettu käyttöön'
|
||||
title: Suojausavaimet käytössä
|
||||
omniauth_callbacks:
|
||||
|
|
|
@ -47,14 +47,19 @@ hu:
|
|||
subject: 'Mastodon: Jelszóvisszaállítási utasítások'
|
||||
title: Jelszó visszaállítása
|
||||
two_factor_disabled:
|
||||
explanation: A bejelentkezés most már csupán email címmel és jelszóval lehetséges.
|
||||
subject: Kétlépcsős azonosítás kikapcsolva
|
||||
subtitle: A kétlépcsős hitelesítés a fiókodhoz ki lett kapcsolva.
|
||||
title: Kétlépcsős hitelesítés kikapcsolva
|
||||
two_factor_enabled:
|
||||
explanation: Egy párosított TOTP appal generált tokenre lesz szükség a bejelentkezéshez.
|
||||
subject: 'Mastodon: Kétlépcsős azonosítás engedélyezve'
|
||||
subtitle: A kétlépcsős hitelesítés a fiókodhoz aktiválva lett.
|
||||
title: Kétlépcsős hitelesítés engedélyezve
|
||||
two_factor_recovery_codes_changed:
|
||||
explanation: A korábbi helyreállítási kódok letiltásra és újragenerálásra kerültek.
|
||||
subject: 'Mastodon: Kétlépcsős helyreállítási kódok újból előállítva'
|
||||
subtitle: A korábbi helyreállítási kódokat letiltottuk, és újakat generáltunk.
|
||||
title: A kétlépcsős kódok megváltoztak
|
||||
unlock_instructions:
|
||||
subject: 'Mastodon: Feloldási utasítások'
|
||||
|
@ -68,9 +73,13 @@ hu:
|
|||
subject: 'Mastodon: A biztonsági kulcs törlésre került'
|
||||
title: Az egyik biztonsági kulcsodat törölték
|
||||
webauthn_disabled:
|
||||
explanation: A biztonsági kulcsokkal történő hitelesítés a fiókodhoz ki lett kapcsolva.
|
||||
extra: A bejelentkezés most már csak TOTP app által generált tokennel lehetséges.
|
||||
subject: 'Mastodon: A biztonsági kulccsal történő hitelesítés letiltásra került'
|
||||
title: A biztonsági kulcsok letiltásra kerültek
|
||||
webauthn_enabled:
|
||||
explanation: A biztonsági kulcsokkal történő hitelesítés a fiókodhoz aktiválva lett.
|
||||
extra: A biztonsági kulcsodat mostantól lehet bejelentkezésre használni.
|
||||
subject: 'Mastodon: A biztonsági kulcsos hitelesítés engedélyezésre került'
|
||||
title: A biztonsági kulcsok engedélyezésre kerültek
|
||||
omniauth_callbacks:
|
||||
|
|
|
@ -52,6 +52,7 @@ ie:
|
|||
subtitle: 2-factor autentication por tui conto ha esset desactivisat.
|
||||
title: 2FA desvalidat
|
||||
two_factor_enabled:
|
||||
explanation: Un clave generat del acuplat TOTP-aplication nu va esser besonat por aperter session.
|
||||
subject: 'Mastodon: 2-factor autentication activat'
|
||||
subtitle: 2-factor autentication ha esset activisat por tui conto.
|
||||
title: 2FA permisset
|
||||
|
@ -73,6 +74,7 @@ ie:
|
|||
title: Un ex tui claves de securitá ha esset deletet
|
||||
webauthn_disabled:
|
||||
explanation: Autentication per clave de securitá ha esset desactivisat por tui conto.
|
||||
extra: Aperter session es nu possibil solmen per li clave generat del acuplat TOTP-aplication.
|
||||
subject: 'Mastodon: Autentication con claves de securitá desactivisat'
|
||||
title: Claves de securitá desactivisat
|
||||
webauthn_enabled:
|
||||
|
|
|
@ -49,12 +49,12 @@ ja:
|
|||
two_factor_disabled:
|
||||
explanation: メールアドレスとパスワードのみでログイン可能になりました。
|
||||
subject: 'Mastodon: 二要素認証が無効になりました'
|
||||
subtitle: 二要素認証が無効になっています。
|
||||
subtitle: 今後、アカウントへのログインに二要素認証を要求しません。
|
||||
title: 二要素認証が無効化されました
|
||||
two_factor_enabled:
|
||||
explanation: ログインには設定済みのTOTPアプリが生成したトークンが必要です。
|
||||
subject: 'Mastodon: 二要素認証が有効になりました'
|
||||
subtitle: 二要素認証が有効になりました。
|
||||
subtitle: 今後、アカウントへのログインに二要素認証が必要になります。
|
||||
title: 二要素認証が有効化されました
|
||||
two_factor_recovery_codes_changed:
|
||||
explanation: 以前のリカバリーコードが無効化され、新しいコードが生成されました。
|
||||
|
@ -73,7 +73,7 @@ ja:
|
|||
subject: 'Mastodon: セキュリティキーが削除されました'
|
||||
title: セキュリティキーが削除されました
|
||||
webauthn_disabled:
|
||||
explanation: セキュリティキー認証が無効になっています。
|
||||
explanation: セキュリティキー認証が無効になりました。
|
||||
extra: 設定済みのTOTPアプリが生成したトークンのみでログインできるようになりました。
|
||||
subject: 'Mastodon: セキュリティキー認証が無効になりました'
|
||||
title: セキュリティキーは無効になっています
|
||||
|
|
|
@ -47,14 +47,19 @@ ko:
|
|||
subject: 'Mastodon: 암호 재설정 설명'
|
||||
title: 암호 재설정
|
||||
two_factor_disabled:
|
||||
explanation: 이제 이메일과 암호만 이용해서 로그인이 가능합니다.
|
||||
subject: '마스토돈: 이중 인증 비활성화'
|
||||
subtitle: 계정에 대한 2단계 인증이 비활성화되었습니다.
|
||||
title: 2FA 비활성화 됨
|
||||
two_factor_enabled:
|
||||
explanation: 로그인 하기 위해서는 짝이 되는 TOTP 앱에서 생성한 토큰이 필요합니다.
|
||||
subject: '마스토돈: 이중 인증 활성화'
|
||||
subtitle: 계정에 대한 2단계 인증이 활성화되었습니다.
|
||||
title: 2FA 활성화 됨
|
||||
two_factor_recovery_codes_changed:
|
||||
explanation: 이전 복구 코드가 무효화되고 새 코드가 생성되었습니다
|
||||
subject: '마스토돈: 이중 인증 복구 코드 재생성 됨'
|
||||
subtitle: 이전 복구 코드가 무효화되고 새 코드가 생성되었습니다.
|
||||
title: 2FA 복구 코드 변경됨
|
||||
unlock_instructions:
|
||||
subject: '마스토돈: 잠금 해제 방법'
|
||||
|
@ -68,9 +73,13 @@ ko:
|
|||
subject: '마스토돈: 보안 키 삭제'
|
||||
title: 보안 키가 삭제되었습니다
|
||||
webauthn_disabled:
|
||||
explanation: 계정의 보안 키 인증이 비활성화되었습니다
|
||||
extra: 이제 TOTP 앱에서 생성한 토큰을 통해서만 로그인 가능합니다.
|
||||
subject: '마스토돈: 보안 키를 이용한 인증이 비활성화 됨'
|
||||
title: 보안 키 비활성화 됨
|
||||
webauthn_enabled:
|
||||
explanation: 계정에 대한 보안키 인증이 활성화되었습니다.
|
||||
extra: 로그인시 보안키가 사용됩니다.
|
||||
subject: '마스토돈: 보안 키 인증 활성화 됨'
|
||||
title: 보안 키 활성화 됨
|
||||
omniauth_callbacks:
|
||||
|
|
|
@ -47,10 +47,14 @@ lad:
|
|||
subject: 'Mastodon: Instruksyones para reinisyar kod'
|
||||
title: Reinisyar kod
|
||||
two_factor_disabled:
|
||||
explanation: Agora puedes konektarte kon tu kuento uzando solo tu adreso de posta i kod.
|
||||
subject: 'Mastodon: La autentifikasyon de dos pasos esta inkapasitada'
|
||||
subtitle: La autentifikasyon en dos pasos para tu kuento tiene sido inkapasitada.
|
||||
title: Autentifikasyon 2FA inkapasitada
|
||||
two_factor_enabled:
|
||||
explanation: Se rekierira un token djenerado por la aplikasyon TOTP konektada para entrar.
|
||||
subject: 'Mastodon: La autentifikasyon de dos pasos esta kapasitada'
|
||||
subtitle: La autentifikasyon de dos pasos para tu kuento tiene sido kapasitada.
|
||||
title: Autentifikasyon 2FA aktivada
|
||||
two_factor_recovery_codes_changed:
|
||||
explanation: Los kodiches de rekuperasyon previos tienen sido invalidados i se djeneraron kodiches muevos.
|
||||
|
@ -69,9 +73,13 @@ lad:
|
|||
subject: 'Mastodon: Yave de sigurita supremida'
|
||||
title: Una de tus yaves de sigurita tiene sido supremida
|
||||
webauthn_disabled:
|
||||
explanation: La autentifikasyon kon yaves de sigurita tiene sido inkapasitada para tu kuento.
|
||||
extra: Agora el inisyo de sesyon solo es posivle utilizando el token djeenerado por la aplikasyon TOTP konektada.
|
||||
subject: 'Mastodon: autentifikasyon kon yaves de sigurita inkapasitada'
|
||||
title: Yaves de sigurita inkapasitadas
|
||||
webauthn_enabled:
|
||||
explanation: La autentifikasyon kon yave de sigurita tiene sido kapasitada para tu kuento.
|
||||
extra: Agora tu yave de sigurita puede ser utilizada para konektarte kon tu kuento.
|
||||
subject: 'Mastodon: Autentifikasyon de yave de sigurita aktivada'
|
||||
title: Yaves de sigurita kapasitadas
|
||||
omniauth_callbacks:
|
||||
|
|
|
@ -47,14 +47,19 @@ nn:
|
|||
subject: 'Mastodon: Instuksjonar for å endra passord'
|
||||
title: Attstilling av passord
|
||||
two_factor_disabled:
|
||||
explanation: Innlogging er nå mulig med kun e-postadresse og passord.
|
||||
subject: 'Mastodon: To-faktor-autentisering deaktivert'
|
||||
subtitle: To-faktor autentisering for din konto har blitt deaktivert.
|
||||
title: 2FA deaktivert
|
||||
two_factor_enabled:
|
||||
explanation: En token generert av den sammenkoblede TOTP-appen vil være påkrevd for innlogging.
|
||||
subject: 'Mastodon: To-faktor-autentisering aktivert'
|
||||
subtitle: Tofaktorautentisering er aktivert for din konto.
|
||||
title: 2FA aktivert
|
||||
two_factor_recovery_codes_changed:
|
||||
explanation: Dei førre gjenopprettingskodane er ugyldige og nye er genererte.
|
||||
subject: 'Mastodon: To-faktor-gjenopprettingskodar har vorte genererte på nytt'
|
||||
subtitle: De forrige gjenopprettingskodene er gjort ugyldige og nye er generert.
|
||||
title: 2FA-gjenopprettingskodane er endra
|
||||
unlock_instructions:
|
||||
subject: 'Mastodon: Instruksjonar for å opne kontoen igjen'
|
||||
|
@ -68,9 +73,13 @@ nn:
|
|||
subject: 'Mastodon: Sikkerheitsnøkkel sletta'
|
||||
title: Ein av sikkerheitsnøklane dine har blitt sletta
|
||||
webauthn_disabled:
|
||||
explanation: Autentisering med sikkerhetsnøkler er deaktivert for kontoen din.
|
||||
extra: Innlogging er nå mulig med kun tilgangstoken generert av den sammenkoblede TOTP-appen.
|
||||
subject: 'Mastodon: Autentisering med sikkerheitsnøklar vart skrudd av'
|
||||
title: Sikkerheitsnøklar deaktivert
|
||||
webauthn_enabled:
|
||||
explanation: Sikkerhetsnøkkelautentisering har blitt aktivert for kontoen din.
|
||||
extra: Sikkerhetsnøkkelen din kan nå bli brukt for innlogging.
|
||||
subject: 'Mastodon: Sikkerheitsnøkkelsautentisering vart skrudd på'
|
||||
title: Sikkerheitsnøklar aktivert
|
||||
omniauth_callbacks:
|
||||
|
|
|
@ -47,14 +47,19 @@
|
|||
subject: 'Mastodon: Hvordan nullstille passord'
|
||||
title: Nullstill passord
|
||||
two_factor_disabled:
|
||||
explanation: Innlogging er nå mulig med kun e-postadresse og passord.
|
||||
subject: 'Mastodon: Tofaktorautentisering deaktivert'
|
||||
subtitle: To-faktor autentisering for din konto har blitt deaktivert.
|
||||
title: 2FA deaktivert
|
||||
two_factor_enabled:
|
||||
explanation: En token generert av den sammenkoblede TOTP-appen vil være påkrevd for innlogging.
|
||||
subject: 'Mastodon: Tofaktorautentisering aktivert'
|
||||
subtitle: Tofaktorautentisering er aktivert for din konto.
|
||||
title: 2FA aktivert
|
||||
two_factor_recovery_codes_changed:
|
||||
explanation: De forrige gjenopprettingskodene er gjort ugyldige og nye er generert.
|
||||
subject: 'Mastodon: Tofaktor-gjenopprettingskoder har blitt generert på nytt'
|
||||
subtitle: De forrige gjenopprettingskodene er gjort ugyldige og nye er generert.
|
||||
title: 2FA-gjenopprettingskodene ble endret
|
||||
unlock_instructions:
|
||||
subject: 'Mastodon: Instruksjoner for å gjenåpne konto'
|
||||
|
@ -68,9 +73,13 @@
|
|||
subject: 'Mastodon: Sikkerhetsnøkkel slettet'
|
||||
title: En av sikkerhetsnøklene dine har blitt slettet
|
||||
webauthn_disabled:
|
||||
explanation: Autentisering med sikkerhetsnøkler er deaktivert for kontoen din.
|
||||
extra: Innlogging er nå mulig med kun tilgangstoken generert av den sammenkoblede TOTP-appen.
|
||||
subject: 'Mastodon: Autentisering med sikkerhetsnøkler ble skrudd av'
|
||||
title: Sikkerhetsnøkler deaktivert
|
||||
webauthn_enabled:
|
||||
explanation: Sikkerhetsnøkkelautentisering har blitt aktivert for kontoen din.
|
||||
extra: Sikkerhetsnøkkelen din kan nå bli brukt for innlogging.
|
||||
subject: 'Mastodon: Sikkerhetsnøkkelsautentisering ble skrudd på'
|
||||
title: Sikkerhetsnøkler aktivert
|
||||
omniauth_callbacks:
|
||||
|
|
|
@ -47,14 +47,19 @@ sl:
|
|||
subject: 'Mastodon: navodila za ponastavitev gesla'
|
||||
title: Ponastavitev gesla
|
||||
two_factor_disabled:
|
||||
explanation: Prijava je sedaj mogoče le z uporabo e-poštnega naslova in gesla.
|
||||
subject: 'Mastodon: dvojno preverjanje pristnosti je onemogočeno'
|
||||
subtitle: Dvo-faktorsko preverjanje pristnosti za vaš račun je bilo onemogočeno.
|
||||
title: 2FA onemogočeno
|
||||
two_factor_enabled:
|
||||
explanation: Za prijavo bo zahtevan žeton, ustvarjen s povezano aplikacijo TOTP.
|
||||
subject: 'Mastodon: dvojno preverjanje pristnosti je omogočeno'
|
||||
subtitle: Dvo-faktorsko preverjanje pristnosti za vaš račun je bilo omogočeno.
|
||||
title: 2FA omogočeno
|
||||
two_factor_recovery_codes_changed:
|
||||
explanation: Prejšnje obnovitvene kode so postale neveljavne in ustvarjene so bile nove.
|
||||
subject: 'Mastodon: varnostne obnovitvene kode za dvojno preverjanje pristnosti so ponovno izdelane'
|
||||
subtitle: Prejšnje kode za obnovitev so bile razveljavljene, ustvarjene pa so bile nove.
|
||||
title: obnovitvene kode 2FA spremenjene
|
||||
unlock_instructions:
|
||||
subject: 'Mastodon: navodila za odklepanje'
|
||||
|
@ -68,9 +73,13 @@ sl:
|
|||
subject: 'Mastodon: varnostna koda izbrisana'
|
||||
title: Ena od vaših varnostnih kod je bila izbrisana
|
||||
webauthn_disabled:
|
||||
explanation: Preverjanje pristnosti z varnostnimi ključi za vaš račun je bilo onemogočeno.
|
||||
extra: Prijava je sedaj mogoče le z uporabo žetona, ustvarjenega s povezano aplikacijo TOTP.
|
||||
subject: 'Mastodon: overjanje pristnosti z varnosnimi kodami je onemogočeno'
|
||||
title: Varnostne kode onemogočene
|
||||
webauthn_enabled:
|
||||
explanation: Preverjanje pristnosti z varnostnimi ključi za vaš račun je bilo omogočeno.
|
||||
extra: Za prijavo sedaj lahko uporabite svoj varnostni ključ.
|
||||
subject: 'Mastodon: preverjanje pristnosti z varnostno kodo je omogočeno'
|
||||
title: Varnostne kode omogočene
|
||||
omniauth_callbacks:
|
||||
|
|
|
@ -47,14 +47,19 @@ th:
|
|||
subject: 'Mastodon: คำแนะนำการตั้งรหัสผ่านใหม่'
|
||||
title: การตั้งรหัสผ่านใหม่
|
||||
two_factor_disabled:
|
||||
explanation: ตอนนี้สามารถเข้าสู่ระบบได้โดยใช้เพียงที่อยู่อีเมลและรหัสผ่านเท่านั้น
|
||||
subject: 'Mastodon: ปิดใช้งานการรับรองความถูกต้องด้วยสองปัจจัยแล้ว'
|
||||
subtitle: ปิดใช้งานการรับรองความถูกต้องด้วยสองปัจจัยสำหรับบัญชีของคุณแล้ว
|
||||
title: ปิดใช้งาน 2FA แล้ว
|
||||
two_factor_enabled:
|
||||
explanation: จะต้องใช้โทเคนที่สร้างโดยแอป TOTP ที่จับคู่สำหรับการเข้าสู่ระบบ
|
||||
subject: 'Mastodon: เปิดใช้งานการรับรองความถูกต้องด้วยสองปัจจัยแล้ว'
|
||||
subtitle: เปิดใช้งานการรับรองความถูกต้องด้วยสองปัจจัยสำหรับบัญชีของคุณแล้ว
|
||||
title: เปิดใช้งาน 2FA แล้ว
|
||||
two_factor_recovery_codes_changed:
|
||||
explanation: ยกเลิกรหัสกู้คืนก่อนหน้านี้และสร้างรหัสใหม่แล้ว
|
||||
explanation: ยกเลิกรหัสกู้คืนก่อนหน้านี้และสร้างรหัสกู้คืนใหม่แล้ว
|
||||
subject: 'Mastodon: สร้างรหัสกู้คืนสองปัจจัยใหม่แล้ว'
|
||||
subtitle: ยกเลิกรหัสกู้คืนก่อนหน้านี้และสร้างรหัสกู้คืนใหม่แล้ว
|
||||
title: เปลี่ยนรหัสกู้คืน 2FA แล้ว
|
||||
unlock_instructions:
|
||||
subject: 'Mastodon: คำแนะนำการปลดล็อค'
|
||||
|
@ -68,9 +73,13 @@ th:
|
|||
subject: 'Mastodon: ลบกุญแจความปลอดภัยแล้ว'
|
||||
title: ลบหนึ่งในกุญแจความปลอดภัยของคุณแล้ว
|
||||
webauthn_disabled:
|
||||
explanation: ปิดใช้งานการรับรองความถูกต้องด้วยกุญแจความปลอดภัยสำหรับบัญชีของคุณแล้ว
|
||||
extra: ตอนนี้สามารถเข้าสู่ระบบได้โดยใช้เพียงโทเคนที่สร้างโดยแอป TOTP ที่จับคู่เท่านั้น
|
||||
subject: 'Mastodon: ปิดใช้งานการรับรองความถูกต้องด้วยกุญแจความปลอดภัยแล้ว'
|
||||
title: ปิดใช้งานกุญแจความปลอดภัยแล้ว
|
||||
webauthn_enabled:
|
||||
explanation: เปิดใช้งานการรับรองความถูกต้องด้วยกุญแจความปลอดภัยสำหรับบัญชีของคุณแล้ว
|
||||
extra: ตอนนี้สามารถใช้กุญแจความปลอดภัยของคุณสำหรับการเข้าสู่ระบบ
|
||||
subject: 'Mastodon: เปิดใช้งานการรับรองความถูกต้องด้วยกุญแจความปลอดภัยแล้ว'
|
||||
title: เปิดใช้งานกุญแจความปลอดภัยแล้ว
|
||||
omniauth_callbacks:
|
||||
|
|
|
@ -17,6 +17,7 @@ ia:
|
|||
index:
|
||||
application: Application
|
||||
delete: Deler
|
||||
empty: Tu non ha applicationes.
|
||||
name: Nomine
|
||||
new: Nove application
|
||||
show: Monstrar
|
||||
|
@ -47,6 +48,7 @@ ia:
|
|||
title:
|
||||
accounts: Contos
|
||||
admin/accounts: Gestion de contos
|
||||
all: Accesso plen a tu conto de Mastodon
|
||||
bookmarks: Marcapaginas
|
||||
conversations: Conversationes
|
||||
favourites: Favoritos
|
||||
|
@ -61,8 +63,15 @@ ia:
|
|||
applications: Applicationes
|
||||
oauth2_provider: Fornitor OAuth2
|
||||
scopes:
|
||||
read:favourites: vider tu favoritos
|
||||
read:lists: vider tu listas
|
||||
read:notifications: vider tu notificationes
|
||||
read:statuses: vider tote le messages
|
||||
write:accounts: modificar tu profilo
|
||||
write:blocks: blocar contos e dominios
|
||||
write:favourites: messages favorite
|
||||
write:filters: crear filtros
|
||||
write:lists: crear listas
|
||||
write:media: incargar files de medios
|
||||
write:notifications: rader tu notificationes
|
||||
write:statuses: publicar messages
|
||||
|
|
|
@ -1791,6 +1791,12 @@ en:
|
|||
extra: It's now ready for download!
|
||||
subject: Your archive is ready for download
|
||||
title: Archive takeout
|
||||
failed_2fa:
|
||||
details: 'Here are details of the sign-in attempt:'
|
||||
explanation: Someone has tried to sign in to your account but provided an invalid second authentication factor.
|
||||
further_actions_html: If this wasn't you, we recommend that you %{action} immediately as it may be compromised.
|
||||
subject: Second factor authentication failure
|
||||
title: Failed second factor authentication
|
||||
suspicious_sign_in:
|
||||
change_password: change your password
|
||||
details: 'Here are details of the sign-in:'
|
||||
|
@ -1844,6 +1850,7 @@ en:
|
|||
go_to_sso_account_settings: Go to your identity provider's account settings
|
||||
invalid_otp_token: Invalid two-factor code
|
||||
otp_lost_help_html: If you lost access to both, you may get in touch with %{email}
|
||||
rate_limited: Too many authentication attempts, try again later.
|
||||
seamless_external_login: You are logged in via an external service, so password and e-mail settings are not available.
|
||||
signed_in_as: 'Signed in as:'
|
||||
verification:
|
||||
|
|
|
@ -309,6 +309,7 @@ eo:
|
|||
unpublish: Malpublikigi
|
||||
unpublished_msg: Anonco sukcese malpublikigita!
|
||||
updated_msg: Anonco sukcese ĝisdatigis!
|
||||
critical_update_pending: Kritika ĝisdatigo pritraktotas
|
||||
custom_emojis:
|
||||
assign_category: Atribui kategorion
|
||||
by_domain: Domajno
|
||||
|
@ -424,6 +425,7 @@ eo:
|
|||
view: Vidi domajna blokado
|
||||
email_domain_blocks:
|
||||
add_new: Aldoni novan
|
||||
allow_registrations_with_approval: Permesi aliĝojn kun aprobo
|
||||
attempts_over_week:
|
||||
one: "%{count} provo ekde lasta semajno"
|
||||
other: "%{count} registroprovoj ekde lasta semajno"
|
||||
|
@ -770,11 +772,21 @@ eo:
|
|||
approved: Bezonas aprobi por aliĝi
|
||||
none: Neniu povas aliĝi
|
||||
open: Iu povas aliĝi
|
||||
security:
|
||||
authorized_fetch: Devigi aŭtentigon de frataraj serviloj
|
||||
title: Agordoj de la servilo
|
||||
site_uploads:
|
||||
delete: Forigi elŝutitan dosieron
|
||||
destroyed_msg: Reteja alŝuto sukcese forigita!
|
||||
software_updates:
|
||||
critical_update: Kritika — bonvolu ĝisdatiĝi rapide
|
||||
documentation_link: Lerni pli
|
||||
release_notes: Eldono-notoj
|
||||
title: Disponeblaj ĝisdatigoj
|
||||
type: Tipo
|
||||
types:
|
||||
major: Ĉefa eldono
|
||||
minor: Neĉefa eldono
|
||||
statuses:
|
||||
account: Skribanto
|
||||
application: Aplikaĵo
|
||||
|
@ -1259,6 +1271,9 @@ eo:
|
|||
overwrite: Anstataŭigi
|
||||
overwrite_long: Anstataŭigi la nunajn registrojn per la novaj
|
||||
preface: Vi povas importi datumojn, kiujn vi eksportis el alia servilo, kiel liston de homoj, kiujn vi sekvas aŭ blokas.
|
||||
states:
|
||||
finished: Finita
|
||||
unconfirmed: Nekonfirmita
|
||||
success: Viaj datumoj estis sukcese alŝutitaj kaj estos traktitaj kiel planite
|
||||
titles:
|
||||
following: Importado de sekvaj kontoj
|
||||
|
@ -1528,6 +1543,7 @@ eo:
|
|||
unknown_browser: Nekonata retumilo
|
||||
weibo: Weibo
|
||||
current_session: Nuna seanco
|
||||
date: Dato
|
||||
description: "%{browser} en %{platform}"
|
||||
explanation: Ĉi tiuj estas la retumiloj nun ensalutintaj al via Mastodon-konto.
|
||||
ip: IP
|
||||
|
@ -1693,6 +1709,7 @@ eo:
|
|||
webauthn: Sekurecaj ŝlosiloj
|
||||
user_mailer:
|
||||
appeal_approved:
|
||||
action: Konto-agordoj
|
||||
explanation: La apelacio de la admono kontra via konto je %{strike_date} pri sendodato %{appeal_date} aprobitas.
|
||||
subject: Via apelacio de %{date} aprobitas
|
||||
title: Apelacio estis aprobita
|
||||
|
@ -1701,6 +1718,7 @@ eo:
|
|||
subject: Via apelacio de %{date} estis malaprobita
|
||||
title: Apelacio estis malaprobita
|
||||
backup_ready:
|
||||
extra: Estas nun preta por elŝuto!
|
||||
subject: Via arkivo estas preta por elŝutado
|
||||
title: Arkiva elŝuto
|
||||
suspicious_sign_in:
|
||||
|
@ -1756,6 +1774,7 @@ eo:
|
|||
go_to_sso_account_settings: Iru al la agordoj de la konto de via identeca provizanto
|
||||
invalid_otp_token: Nevalida kodo de dufaktora aŭtentigo
|
||||
otp_lost_help_html: Se vi perdas aliron al ambaŭ, vi povas kontakti %{email}
|
||||
rate_limited: Estas tro multaj aŭtentigaj provoj, reprovu poste.
|
||||
seamless_external_login: Vi estas ensalutinta per ekstera servo, do pasvortaj kaj retadresaj agordoj ne estas disponeblaj.
|
||||
signed_in_as: 'Salutinta kiel:'
|
||||
verification:
|
||||
|
|
|
@ -1843,6 +1843,7 @@ es-AR:
|
|||
go_to_sso_account_settings: Andá a la configuración de cuenta de tu proveedor de identidad
|
||||
invalid_otp_token: Código de dos factores no válido
|
||||
otp_lost_help_html: Si perdiste al acceso a ambos, podés ponerte en contacto con %{email}
|
||||
rate_limited: Demasiados intentos de autenticación; intentá de nuevo más tarde.
|
||||
seamless_external_login: Iniciaste sesión desde un servicio externo, así que la configuración de contraseña y correo electrónico no están disponibles.
|
||||
signed_in_as: 'Iniciaste sesión como:'
|
||||
verification:
|
||||
|
|
|
@ -1843,6 +1843,7 @@ es-MX:
|
|||
go_to_sso_account_settings: Diríjete a la configuración de la cuenta de su proveedor de identidad
|
||||
invalid_otp_token: Código de dos factores incorrecto
|
||||
otp_lost_help_html: Si perdiste al acceso a ambos, puedes ponerte en contancto con %{email}
|
||||
rate_limited: Demasiados intentos de autenticación, inténtalo de nuevo más tarde.
|
||||
seamless_external_login: Has iniciado sesión desde un servicio externo, así que los ajustes de contraseña y correo no están disponibles.
|
||||
signed_in_as: 'Sesión iniciada como:'
|
||||
verification:
|
||||
|
|
|
@ -1843,6 +1843,7 @@ es:
|
|||
go_to_sso_account_settings: Diríjase a la configuración de la cuenta de su proveedor de identidad
|
||||
invalid_otp_token: Código de dos factores incorrecto
|
||||
otp_lost_help_html: Si perdiste al acceso a ambos, puedes ponerte en contancto con %{email}
|
||||
rate_limited: Demasiados intentos de autenticación, inténtalo de nuevo más tarde.
|
||||
seamless_external_login: Has iniciado sesión desde un servicio externo, así que los ajustes de contraseña y correo no están disponibles.
|
||||
signed_in_as: 'Sesión iniciada como:'
|
||||
verification:
|
||||
|
|
|
@ -1847,6 +1847,7 @@ eu:
|
|||
go_to_sso_account_settings: Jo zure identitate-hornitzaileko kontuaren ezarpenetara
|
||||
invalid_otp_token: Bi faktoreetako kode baliogabea
|
||||
otp_lost_help_html: 'Bietara sarbidea galdu baduzu, jarri kontaktuan hemen: %{email}'
|
||||
rate_limited: Autentifikazio saiakera gehiegi, saiatu berriro geroago.
|
||||
seamless_external_login: Kanpo zerbitzu baten bidez hasi duzu saioa, beraz pasahitza eta e-mail ezarpenak ez daude eskuragarri.
|
||||
signed_in_as: 'Saioa honela hasita:'
|
||||
verification:
|
||||
|
|
|
@ -1608,6 +1608,7 @@ fi:
|
|||
unknown_browser: Tuntematon selain
|
||||
weibo: Weibo
|
||||
current_session: Nykyinen istunto
|
||||
date: Päiväys
|
||||
description: "%{browser} alustalla %{platform}"
|
||||
explanation: Nämä verkkoselaimet ovat tällä hetkellä kirjautuneena Mastodon-tilillesi.
|
||||
ip: IP-osoite
|
||||
|
@ -1774,14 +1775,19 @@ fi:
|
|||
webauthn: Suojausavaimet
|
||||
user_mailer:
|
||||
appeal_approved:
|
||||
action: Tilin asetukset
|
||||
explanation: Valitus tiliäsi koskevasta varoituksesta %{strike_date} jonka lähetit %{appeal_date} on hyväksytty. Tilisi on jälleen hyvässä kunnossa.
|
||||
subject: Valituksesi %{date} on hyväksytty
|
||||
subtitle: Tilisi on jälleen normaalissa tilassa.
|
||||
title: Valitus hyväksytty
|
||||
appeal_rejected:
|
||||
explanation: Valitus tiliäsi koskevasta varoituksesta %{strike_date} jonka lähetit %{appeal_date} on hylätty.
|
||||
subject: Valituksesi %{date} on hylätty
|
||||
subtitle: Vetoomuksesi on hylätty.
|
||||
title: Valitus hylätty
|
||||
backup_ready:
|
||||
explanation: Olet pyytänyt täyden varmuuskopion Mastodon-tilistäsi.
|
||||
extra: Se on nyt valmis ladattavaksi!
|
||||
subject: Arkisto on valmiina ladattavaksi
|
||||
title: Arkiston tallennus
|
||||
suspicious_sign_in:
|
||||
|
@ -1837,6 +1843,7 @@ fi:
|
|||
go_to_sso_account_settings: Avaa identiteettitarjoajasi tiliasetukset
|
||||
invalid_otp_token: Virheellinen kaksivaiheisen todentamisen koodi
|
||||
otp_lost_help_html: Jos sinulla ei ole pääsyä kumpaankaan, voit ottaa yhteyden osoitteeseen %{email}
|
||||
rate_limited: Liian monta todennusyritystä. Yritä myöhemmin uudelleen.
|
||||
seamless_external_login: Olet kirjautunut ulkoisen palvelun kautta, joten salasana- ja sähköpostiasetukset eivät ole käytettävissä.
|
||||
signed_in_as: 'Kirjautunut tilillä:'
|
||||
verification:
|
||||
|
|
|
@ -1843,6 +1843,7 @@ fo:
|
|||
go_to_sso_account_settings: Far til kontustillingarnar hjá samleikaveitaranum hjá tær
|
||||
invalid_otp_token: Ógyldug tvey-stigs koda
|
||||
otp_lost_help_html: Hevur tú mist atgongd til bæði, so kanst tú koma í samband við %{email}
|
||||
rate_limited: Ov nógvar samgildisroyndir, royn aftur seinni.
|
||||
seamless_external_login: Tú er ritað/ur inn umvegis eina uttanhýsis tænastu, so loyniorð og teldupoststillingar eru ikki tøkar.
|
||||
signed_in_as: 'Ritað/ur inn sum:'
|
||||
verification:
|
||||
|
|
|
@ -1843,6 +1843,7 @@ gl:
|
|||
go_to_sso_account_settings: Ir aos axustes da conta no teu provedor de identidade
|
||||
invalid_otp_token: O código do segundo factor non é válido
|
||||
otp_lost_help_html: Se perdes o acceso a ambos, podes contactar con %{email}
|
||||
rate_limited: Demasiados intentos de autenticación, inténtao máis tarde.
|
||||
seamless_external_login: Accedeches a través dun servizo externo, polo que os axustes de contrasinal e email non están dispoñibles.
|
||||
signed_in_as: 'Rexistrada como:'
|
||||
verification:
|
||||
|
|
|
@ -1907,6 +1907,7 @@ he:
|
|||
go_to_sso_account_settings: מעבר לאפיוני החשבון שלך בשרת הזהות
|
||||
invalid_otp_token: קוד דו-שלבי שגוי
|
||||
otp_lost_help_html: אם איבדת גישה לשניהם, ניתן ליצור קשר ב-%{email}
|
||||
rate_limited: יותר מדי ניסיונות אימות, נסו שוב מאוחר יותר.
|
||||
seamless_external_login: את.ה מחובר דרך שירות חיצוני, לכן אפשרויות הסיסמא והדוא"ל לא מאופשרות.
|
||||
signed_in_as: 'מחובר בתור:'
|
||||
verification:
|
||||
|
|
|
@ -1608,6 +1608,7 @@ hu:
|
|||
unknown_browser: Ismeretlen böngésző
|
||||
weibo: Weibo
|
||||
current_session: Jelenlegi munkamenet
|
||||
date: Dátum
|
||||
description: "%{browser} az alábbi platformon: %{platform}"
|
||||
explanation: Jelenleg az alábbi böngészőkkel vagy bejelentkezve a fiókodba.
|
||||
ip: IP
|
||||
|
@ -1774,14 +1775,19 @@ hu:
|
|||
webauthn: Biztonsági kulcsok
|
||||
user_mailer:
|
||||
appeal_approved:
|
||||
action: Fiók Beállításai
|
||||
explanation: A fiókod %{appeal_date}-i fellebbezése, mely a %{strike_date}-i vétségeddel kapcsolatos, jóváhagyásra került. A fiókod megint makulátlan.
|
||||
subject: A %{date}-i fellebbezésedet jóváhagyták
|
||||
subtitle: A fiókod ismét használható állapotban van.
|
||||
title: Fellebbezés jóváhagyva
|
||||
appeal_rejected:
|
||||
explanation: A %{appeal_date}-i fellebbezésed, amely a fiókod %{strike_date}-i vétségével kapcsolatos, elutasításra került.
|
||||
subject: A %{date}-i fellebbezésedet visszautasították
|
||||
subtitle: A fellebbezésedet visszautasították.
|
||||
title: Fellebbezés visszautasítva
|
||||
backup_ready:
|
||||
explanation: A Mastodon fiókod teljes biztonsági mentését kérted.
|
||||
extra: Már letöltésre kész!
|
||||
subject: Az adataidról készült archív letöltésre kész
|
||||
title: Archiválás
|
||||
suspicious_sign_in:
|
||||
|
@ -1837,6 +1843,7 @@ hu:
|
|||
go_to_sso_account_settings: Ugrás az azonosítási szolgáltatód fiókbeállításaihoz
|
||||
invalid_otp_token: Érvénytelen ellenőrző kód
|
||||
otp_lost_help_html: Ha mindkettőt elvesztetted, kérhetsz segítséget itt %{email}
|
||||
rate_limited: Túl sok hiteleítési kísérlet történt. Próbáld újra később.
|
||||
seamless_external_login: Külső szolgáltatáson keresztül jelentkeztél be, így a jelszó és e-mail beállítások nem elérhetőek.
|
||||
signed_in_as: Bejelentkezve mint
|
||||
verification:
|
||||
|
|
|
@ -1786,6 +1786,7 @@ ie:
|
|||
subtitle: Tui apelle ha esset rejectet.
|
||||
title: Apelle rejectet
|
||||
backup_ready:
|
||||
explanation: Tu petit un complet archive de tui conto de Mastodon.
|
||||
extra: It es ja pret a descargar!
|
||||
subject: Tui archive es pret por descargar
|
||||
title: Descargar archive
|
||||
|
@ -1842,6 +1843,7 @@ ie:
|
|||
go_to_sso_account_settings: Ear al parametres de conto de tui provisor de identification
|
||||
invalid_otp_token: Ínvalid 2-factor code
|
||||
otp_lost_help_html: Si tu perdit accesse a ambis, tu posse contacter %{email}
|
||||
rate_limited: Tro mult de provas de autentication, ples provar denov plu tard.
|
||||
seamless_external_login: Tu ha intrat per un servicie external, dunc parametres pri tui passa-parol e email-adresse ne es disponibil.
|
||||
signed_in_as: 'Session apertet quam:'
|
||||
verification:
|
||||
|
|
|
@ -1847,6 +1847,7 @@ is:
|
|||
go_to_sso_account_settings: Fara í stillingar aðgangsins hjá auðkennisveitunni þinni
|
||||
invalid_otp_token: Ógildur tveggja-þátta kóði
|
||||
otp_lost_help_html: Ef þú hefur misst aðganginn að hvoru tveggja, geturðu sett þig í samband við %{email}
|
||||
rate_limited: Of margar tilraunir til auðkenningar, prófaðu aftur síðar.
|
||||
seamless_external_login: Innskráning þín er í gegnum utanaðkomandi þjónustu, þannig að stillingar fyrir lykilorð og tölvupóst eru ekki aðgengilegar.
|
||||
signed_in_as: 'Skráð inn sem:'
|
||||
verification:
|
||||
|
|
|
@ -1845,6 +1845,7 @@ it:
|
|||
go_to_sso_account_settings: Vai alle impostazioni dell'account del tuo provider di identità
|
||||
invalid_otp_token: Codice d'accesso non valido
|
||||
otp_lost_help_html: Se perdessi l'accesso ad entrambi, puoi entrare in contatto con %{email}
|
||||
rate_limited: Troppi tentativi di autenticazione, per favore riprova più tardi.
|
||||
seamless_external_login: Hai effettuato l'accesso tramite un servizio esterno, quindi le impostazioni di password e e-mail non sono disponibili.
|
||||
signed_in_as: 'Hai effettuato l''accesso come:'
|
||||
verification:
|
||||
|
|
|
@ -1813,6 +1813,7 @@ ja:
|
|||
go_to_sso_account_settings: 外部サービスアカウントの設定はこちらで行ってください
|
||||
invalid_otp_token: 二要素認証コードが間違っています
|
||||
otp_lost_help_html: どちらも使用できない場合、%{email}に連絡を取ると解決できるかもしれません
|
||||
rate_limited: 認証に失敗した回数が多すぎます。時間をおいてからログインしてください。
|
||||
seamless_external_login: あなたは外部サービスを介してログインしているため、パスワードとメールアドレスの設定は利用できません。
|
||||
signed_in_as: '下記でログイン中:'
|
||||
verification:
|
||||
|
|
|
@ -1584,6 +1584,7 @@ ko:
|
|||
unknown_browser: 알 수 없는 브라우저
|
||||
weibo: 웨이보
|
||||
current_session: 현재 세션
|
||||
date: 날짜
|
||||
description: "%{platform}의 %{browser}"
|
||||
explanation: 내 마스토돈 계정에 로그인되어 있는 웹 브라우저 목록입니다.
|
||||
ip: IP
|
||||
|
@ -1744,14 +1745,19 @@ ko:
|
|||
webauthn: 보안 키
|
||||
user_mailer:
|
||||
appeal_approved:
|
||||
action: 계정 설정
|
||||
explanation: "%{strike_date}에 일어난 중재결정에 대한 소명을 %{appeal_date}에 작성했으며 승낙되었습니다. 당신의 계정은 정상적인 상태로 돌아왔습니다."
|
||||
subject: 귀하가 %{date}에 작성한 소명이 승낙되었습니다
|
||||
subtitle: 계정이 다시 정상적인 상태입니다.
|
||||
title: 소명이 받아들여짐
|
||||
appeal_rejected:
|
||||
explanation: "%{strike_date}에 일어난 중재결정에 대한 소명을 %{appeal_date}에 작성했지만 반려되었습니다."
|
||||
subject: "%{date}에 작성한 소명이 반려되었습니다."
|
||||
subtitle: 소명이 기각되었습니다.
|
||||
title: 이의 제기가 거절되었습니다
|
||||
backup_ready:
|
||||
explanation: 마스토돈 계정에 대한 전체 백업을 요청했습니다
|
||||
extra: 다운로드 할 준비가 되었습니다!
|
||||
subject: 아카이브를 다운로드할 수 있습니다
|
||||
title: 아카이브 테이크아웃
|
||||
suspicious_sign_in:
|
||||
|
@ -1807,6 +1813,7 @@ ko:
|
|||
go_to_sso_account_settings: ID 공급자의 계정 설정으로 이동
|
||||
invalid_otp_token: 2단계 인증 코드가 올바르지 않습니다
|
||||
otp_lost_help_html: 만약 양쪽 모두를 잃어버렸다면 %{email}을 통해 복구할 수 있습니다
|
||||
rate_limited: 너무 많은 인증 시도가 있었습니다, 잠시 후에 시도하세요.
|
||||
seamless_external_login: 외부 서비스를 이용해 로그인했으므로 이메일과 암호는 설정할 수 없습니다.
|
||||
signed_in_as: '다음과 같이 로그인 중:'
|
||||
verification:
|
||||
|
|
|
@ -384,6 +384,7 @@ lad:
|
|||
cancel: Anula
|
||||
confirm: Suspende
|
||||
permanent_action: Si kites la suspensyon no restoraras dingunos datos ni relasyones.
|
||||
preamble_html: Estas a punto de suspender <strong>%{domain}</strong> i sus subdomenos.
|
||||
remove_all_data: Esto efasara todo el kontenido, multimedia i datos de profiles de los kuentos en este domeno de tu sirvidor.
|
||||
stop_communication: Tu sirvidor deshara de komunikarse kon estos sirvidores.
|
||||
title: Konfirma bloko de domeno para %{domain}
|
||||
|
@ -608,6 +609,7 @@ lad:
|
|||
created_at: Raportado
|
||||
delete_and_resolve: Efasa publikasyones
|
||||
forwarded: Reembiado
|
||||
forwarded_replies_explanation: Este raporto vyene de un utilizador remoto i es sovre kontenido remoto. Tiene sido reembiado a ti porke el kontenido raportado esta en una repuesta a uno de tus utilizadores.
|
||||
forwarded_to: Reembiado a %{domain}
|
||||
mark_as_resolved: Marka komo rezolvido
|
||||
mark_as_sensitive: Marka komo sensivle
|
||||
|
@ -712,6 +714,7 @@ lad:
|
|||
manage_users: Administra utilizadores
|
||||
manage_users_description: Permete a los utilizadores ver los peratim de otros utilizadores i realizar aksyones de moderasyon kontra eyos
|
||||
manage_webhooks: Administrar webhooks
|
||||
manage_webhooks_description: Permite a los utilizadores konfigurar webhooks para evenimientos administrativos
|
||||
view_audit_log: Mostra defter de revisyon
|
||||
view_audit_log_description: Permete a los utilizadores ver una estoria de aksyones administrativas en el sirvidor
|
||||
view_dashboard: Ve pano
|
||||
|
@ -738,6 +741,8 @@ lad:
|
|||
branding:
|
||||
preamble: La marka de tu sirvidor lo desferensia de otros sirvidores de la red. Esta enformasyon puede amostrarse por una varieta de entornos, komo en la enterfaz web de Mastodon, en aplikasyones nativas, en previsualizasiones de atadijos en otros sitios internetikos i en aplikasyones de mesajes, etc. Por esta razon, es mijor mantener esta enformasyon klara, breve i konsiza.
|
||||
title: Marka
|
||||
captcha_enabled:
|
||||
title: Solisita ke los muevos utilizadores rezolven un CAPTCHA para konfirmar su konto
|
||||
content_retention:
|
||||
preamble: Kontrola komo el kontenido jenerado por el utilizador se magazina en Mastodon.
|
||||
title: Retensyon de kontenido
|
||||
|
@ -765,6 +770,9 @@ lad:
|
|||
approved: Se rekiere achetasion para enrejistrarse
|
||||
none: Permete a los utilizadores trokar la konfigurasyon del sitio
|
||||
open: Kualkiera puede enrejistrarse
|
||||
security:
|
||||
authorized_fetch_overridden_hint: Agora no puedes trokar esta konfigurasyon dkee esta sovreeskrita por una variable de entorno.
|
||||
federation_authentication: Forzamyento de autentifikasyon para la federasyon
|
||||
title: Konfigurasyon del sirvidor
|
||||
site_uploads:
|
||||
delete: Efasa dosya kargada
|
||||
|
@ -820,8 +828,13 @@ lad:
|
|||
system_checks:
|
||||
database_schema_check:
|
||||
message_html: Ay migrasyones asperando de la baza de datos. Por favor, egzekutalas para asigurarte de ke la aplikasyon fonksiona komo deveria
|
||||
elasticsearch_health_red:
|
||||
message_html: El klaster de Elasticsearch no es sano (estado kolorado), funksyones de bushkeda no estan disponivles
|
||||
elasticsearch_health_yellow:
|
||||
message_html: El klaster de Elasticsearch no es sano (estado amariyo), es posivle ke keras investigar la razon
|
||||
elasticsearch_preset:
|
||||
action: Ve dokumentasyon
|
||||
message_html: Tu klaster de Elasticsearch tiene mas ke un nodo, ama Mastodon no esta konfigurado para uzarlos.
|
||||
elasticsearch_preset_single_node:
|
||||
action: Ve dokumentasyon
|
||||
elasticsearch_running_check:
|
||||
|
@ -1012,12 +1025,17 @@ lad:
|
|||
auth:
|
||||
apply_for_account: Solisita un kuento
|
||||
captcha_confirmation:
|
||||
help_html: Si tyenes problemas kon rezolver el CAPTCHA, puedes kontaktarnos en %{email} i podremos ayudarte.
|
||||
hint_html: Una koza mas! Tenemos ke konfirmar ke eres umano (para evitar spam!). Rezolve el CAPTCHA abasho i klika "Kontinua".
|
||||
title: Kontrolo de sigurita
|
||||
confirmations:
|
||||
awaiting_review: Tu adreso de posta tiene sido konfirmado! La taifa de %{domain} esta revizando tu enrejistrasyon. Risiviras un meil si acheten tu kuento!
|
||||
awaiting_review_title: Estamos revizando tu enrejistramiento
|
||||
clicking_this_link: klikando en este atadijo
|
||||
login_link: konektate kon kuento
|
||||
proceed_to_login_html: Agora puedes ir a %{login_link}.
|
||||
redirect_to_app_html: Seras readresado a la aplikasyon <strong>%{app_name}</strong>. Si esto no afita, aprova %{clicking_this_link} o regresa manualmente a la aplikasyon.
|
||||
registration_complete: Tu enrejistrasyon en %{domain} ya esta kompletada!
|
||||
welcome_title: Bienvenido, %{name}!
|
||||
wrong_email_hint: Si este adreso de posta es inkorekto, puedes trokarlo en las preferensyas del kuento.
|
||||
delete_account: Efasa kuento
|
||||
|
@ -1054,6 +1072,7 @@ lad:
|
|||
rules:
|
||||
accept: Acheta
|
||||
back: Atras
|
||||
invited_by: 'Puedes adjuntarte a %{domain} grasyas a la envitasyon de:'
|
||||
preamble: Estas son establesidas i aplikadas por los moderadores de %{domain}.
|
||||
preamble_invited: Antes de kontinuar, por favor reviza las reglas del sirvidor establesidas por los moderatores de %{domain}.
|
||||
title: Algunas reglas bazikas.
|
||||
|
@ -1078,6 +1097,7 @@ lad:
|
|||
functional: Tu kuento esta kompletamente funksyonal.
|
||||
pending: Tu solisitasyon esta asperando la revizion por muestros administradores. Esto puede tadrar algun tiempo. Arisiviras una posta elektronika si la solisitasyon sea achetada.
|
||||
redirecting_to: Tu kuento se topa inaktivo porke esta siendo readresado a %{acct}.
|
||||
self_destruct: Deke %{domain} va a serrarse, solo tendras akseso limitado a tu kuento.
|
||||
view_strikes: Ve amonestamientos pasados kontra tu kuento
|
||||
too_fast: Formulario enviado demaziado rapido, aprovalo de muevo.
|
||||
use_security_key: Uza la yave de sigurita
|
||||
|
@ -1271,6 +1291,19 @@ lad:
|
|||
merge_long: Manten rejistros egzistentes i adjusta muevos
|
||||
overwrite: Sobreskrive
|
||||
overwrite_long: Mete muevos rejistros en vez de los aktuales
|
||||
overwrite_preambles:
|
||||
blocking_html: Estas a punto de <strong>substituyir tu lista de blokos</strong> por asta <strong>%{total_items} kuentos </strong> de <strong>%{filename}</strong>.
|
||||
bookmarks_html: Estas a punto de <strong>substituyir tus markadores</strong> por asta <strong>%{total_items} publikasyones</strong> ke vinyeron de <strong>%{filename}</strong>.
|
||||
domain_blocking_html: Estas a punto de <strong>substituyir tu lista de blokos de domeno</strong> por asta <strong>%{total_items} domenos </strong> de <strong>%{filename}</strong>.
|
||||
following_html: Estas a punto de <strong>segir</strong> asta <strong>%{total_items} kuentos</strong> de <strong>%{filename}</strong> i <strong>deshar de segir todos los otros kuentos</strong>.
|
||||
lists_html: Estas a punto de <strong>sustituyir tus listas</strong> con el kontenido de <strong>%{filename}</strong>. Asta <strong>%{total_items} kuentos</strong> seran adjustados a muevas listas.
|
||||
muting_html: Estas a punto de <strong>substituyir tu lista de kuentos silensyados</strong> por asta <strong>%{total_items} kuentos </strong> de <strong>%{filename}</strong>.
|
||||
preambles:
|
||||
blocking_html: Estas a punto de <strong>blokar</strong> asta <strong>%{total_items} kuentos </strong> de <strong>%{filename}</strong>.
|
||||
bookmarks_html: Estas a punto de adjustar asta <strong>%{total_items} publikasyones</strong> de <strong>%{filename}</strong> a tus <strong>markadores</strong>.
|
||||
domain_blocking_html: Estas a punto de <strong>blokar</strong> asta <strong>%{total_items} domenos </strong> de <strong>%{filename}</strong>.
|
||||
following_html: Estas a punto de <strong>segir</strong> asta <strong>%{total_items} kuentos </strong> de <strong>%{filename}</strong>.
|
||||
muting_html: Estas a punto de <strong>silensyar</strong> asta <strong>%{total_items} kuentos </strong> de <strong>%{filename}</strong>.
|
||||
preface: Puedes importar siertos datos, komo todas las personas a las kualas estas sigiendo o blokando en tu kuento en esta instansya, dizde dosyas eksportadas de otra instansya.
|
||||
recent_imports: Importasyones resyentes
|
||||
states:
|
||||
|
@ -1474,7 +1507,9 @@ lad:
|
|||
public_timelines: Linyas de tiempo publikas
|
||||
privacy:
|
||||
privacy: Privasita
|
||||
reach: Alkanse
|
||||
search: Bushkeda
|
||||
title: Privasita i alkanse
|
||||
privacy_policy:
|
||||
title: Politika de privasita
|
||||
reactions:
|
||||
|
@ -1711,6 +1746,7 @@ lad:
|
|||
action: Preferensyas de kuento
|
||||
explanation: La apelasyon del amonestamiento kontra tu kuento del %{strike_date} ke mandates el %{appeal_date} fue achetada. Tu kuento se topa de muevo en dobro estado.
|
||||
subject: Tu apelasyon del %{date} fue achetada
|
||||
subtitle: Tu konto de muevo tiene una reputasyon buena.
|
||||
title: Apelasyon achetada
|
||||
appeal_rejected:
|
||||
explanation: La apelasyon del amonestamiento kontra tu kuento del %{strike_date} ke mandates el %{appeal_date} fue refuzada.
|
||||
|
@ -1718,6 +1754,7 @@ lad:
|
|||
subtitle: Tu apelasyon fue refuzada.
|
||||
title: Apelasyon refuzada
|
||||
backup_ready:
|
||||
extra: Agora esta pronto para abashar!
|
||||
subject: Tu dosya esta pronta para abashar
|
||||
title: Abasha dosya
|
||||
suspicious_sign_in:
|
||||
|
@ -1773,6 +1810,8 @@ lad:
|
|||
go_to_sso_account_settings: Va a la konfigurasyon de kuento de tu prokurador de identita
|
||||
invalid_otp_token: Kodiche de dos pasos no valido
|
||||
otp_lost_help_html: Si pedriste akseso a los dos, puedes kontaktarte kon %{email}
|
||||
rate_limited: Demaziadas provas de autentifikasyon, aprova de muevo dempues.
|
||||
seamless_external_login: Estas konektado por un servisyo eksterno i estonses la konfigurasyon de kod i konto de posta no estan disponivles.
|
||||
signed_in_as: 'Konektado komo:'
|
||||
verification:
|
||||
here_is_how: Ansina es komo
|
||||
|
@ -1785,6 +1824,7 @@ lad:
|
|||
success: Tu yave de sigurita fue adjustada kon sukseso.
|
||||
delete: Efasa
|
||||
delete_confirmation: Estas siguro ke keres efasar esta yave de sigurita?
|
||||
description_html: Si kapasites <strong>autentifikasyon kon yave de sigurita</strong>, nesesitaras uno de tus yaves de sigurita para konektarte kon tu kuento.
|
||||
destroy:
|
||||
error: Uvo un problem al efasar tu yave de sigurita. Por favor aprova de muevo.
|
||||
success: Tu yave de sigurita fue efasada kon sukseso.
|
||||
|
|
|
@ -1843,6 +1843,7 @@ nl:
|
|||
go_to_sso_account_settings: Ga naar de accountinstellingen van je identiteitsprovider
|
||||
invalid_otp_token: Ongeldige tweestaps-toegangscode
|
||||
otp_lost_help_html: Als je toegang tot beiden kwijt bent geraakt, neem dan contact op via %{email}
|
||||
rate_limited: Te veel authenticatiepogingen, probeer het later opnieuw.
|
||||
seamless_external_login: Je bent ingelogd via een externe dienst, daarom zijn wachtwoorden en e-mailinstellingen niet beschikbaar.
|
||||
signed_in_as: 'Ingelogd als:'
|
||||
verification:
|
||||
|
|
|
@ -1608,6 +1608,7 @@ nn:
|
|||
unknown_browser: Ukjend nettlesar
|
||||
weibo: Weibo
|
||||
current_session: Noverande økt
|
||||
date: Dato
|
||||
description: "%{browser} på %{platform}"
|
||||
explanation: Desse nettlesarane er logga inn på Mastodon-kontoen din.
|
||||
ip: IP-adresse
|
||||
|
@ -1774,14 +1775,19 @@ nn:
|
|||
webauthn: Sikkerhetsnøkler
|
||||
user_mailer:
|
||||
appeal_approved:
|
||||
action: Kontoinnstillinger
|
||||
explanation: Apellen på prikken mot din kontor på %{strike_date} som du la inn på %{appeal_date} har blitt godkjend. Din konto er nok ein gong i god stand.
|
||||
subject: Din klage fra %{date} er godkjent
|
||||
subtitle: Kontoen din er tilbake i god stand.
|
||||
title: Anke godkjend
|
||||
appeal_rejected:
|
||||
explanation: Klagen på advarselen mot din konto den %{strike_date} som du sendte inn den %{appeal_date} har blitt avvist.
|
||||
subject: Din klage fra %{date} er avvist
|
||||
subtitle: Anken din har blitt avvist.
|
||||
title: Anke avvist
|
||||
backup_ready:
|
||||
explanation: Du etterspurte en fullstendig sikkerhetskopi av din Mastodon-konto.
|
||||
extra: Den er nå klar for nedlasting!
|
||||
subject: Arkivet ditt er klart til å lastes ned
|
||||
title: Nedlasting av arkiv
|
||||
suspicious_sign_in:
|
||||
|
@ -1837,6 +1843,7 @@ nn:
|
|||
go_to_sso_account_settings: Gå til kontoinnstillingane hjå identitetsleverandøren din
|
||||
invalid_otp_token: Ugyldig tostegskode
|
||||
otp_lost_help_html: Hvis du mistet tilgangen til begge deler, kan du komme i kontakt med %{email}
|
||||
rate_limited: For mange autentiseringsforsøk, prøv igjen seinare.
|
||||
seamless_external_login: Du er logga inn gjennom eit eksternt reiskap, so passord og e-postinstillingar er ikkje tilgjengelege.
|
||||
signed_in_as: 'Logga inn som:'
|
||||
verification:
|
||||
|
|
|
@ -229,7 +229,7 @@
|
|||
update_status: Oppdater statusen
|
||||
update_user_role: Oppdater rolle
|
||||
actions:
|
||||
approve_appeal_html: "%{name} godkjente klagen på modereringa fra %{target}"
|
||||
approve_appeal_html: "%{name} godkjente anken på moderering fra %{target}"
|
||||
approve_user_html: "%{name} godkjente registrering fra %{target}"
|
||||
assigned_to_self_report_html: "%{name} tildelte rapport %{target} til seg selv"
|
||||
change_email_user_html: "%{name} endret e-postadressen til brukeren %{target}"
|
||||
|
@ -266,7 +266,7 @@
|
|||
enable_user_html: "%{name} aktiverte innlogging for bruker %{target}"
|
||||
memorialize_account_html: "%{name} endret %{target}s konto til en minneside"
|
||||
promote_user_html: "%{name} forfremmet bruker %{target}"
|
||||
reject_appeal_html: "%{name} avviste moderasjonsavgjørelsesklagen fra %{target}"
|
||||
reject_appeal_html: "%{name} avviste anken på moderering fra %{target}"
|
||||
reject_user_html: "%{name} avslo registrering fra %{target}"
|
||||
remove_avatar_user_html: "%{name} fjernet %{target} sitt profilbilde"
|
||||
reopen_report_html: "%{name} gjenåpnet rapporten %{target}"
|
||||
|
@ -372,8 +372,8 @@
|
|||
website: Nettside
|
||||
disputes:
|
||||
appeals:
|
||||
empty: Ingen klager funnet.
|
||||
title: Klager
|
||||
empty: Ingen anker funnet.
|
||||
title: Anker
|
||||
domain_allows:
|
||||
add_new: Hvitelist domene
|
||||
created_msg: Domenet har blitt hvitelistet
|
||||
|
@ -692,8 +692,8 @@
|
|||
invite_users_description: Lar brukere invitere nye personer til serveren
|
||||
manage_announcements: Behandle Kunngjøringer
|
||||
manage_announcements_description: Lar brukere endre kunngjøringer på serveren
|
||||
manage_appeals: Behandle klager
|
||||
manage_appeals_description: Lar brukere gjennomgå klager mot modereringsaktiviteter
|
||||
manage_appeals: Behandle anker
|
||||
manage_appeals_description: Lar brukere gjennomgå anker mot modereringsaktiviteter
|
||||
manage_blocks: Behandle Blokker
|
||||
manage_blocks_description: Lar brukere blokkere e-postleverandører og IP-adresser
|
||||
manage_custom_emojis: Administrer egendefinerte Emojier
|
||||
|
@ -829,8 +829,8 @@
|
|||
sensitive: "%{name} merket %{target}s konto som følsom"
|
||||
silence: "%{name} begrenset %{target}s konto"
|
||||
suspend: "%{name} suspenderte %{target}s konto"
|
||||
appeal_approved: Klage tatt til følge
|
||||
appeal_pending: Klage behandles
|
||||
appeal_approved: Anket
|
||||
appeal_pending: Anke behandles
|
||||
appeal_rejected: Anke avvist
|
||||
system_checks:
|
||||
database_schema_check:
|
||||
|
@ -975,9 +975,9 @@
|
|||
sensitive: å merke kontoen sin som følsom
|
||||
silence: for å begrense deres konto
|
||||
suspend: for å avslutte kontoen
|
||||
body: "%{target} klager på en moderasjonsbeslutning av %{action_taken_by} fra %{date}, noe som var %{type}. De skrev:"
|
||||
next_steps: Du kan godkjenne klagen for å angre på moderasjonsvedtaket eller ignorere det.
|
||||
subject: "%{username} klager på en moderasjonsbeslutning for %{instance}"
|
||||
body: "%{target} anker en moderasjonsbeslutning av %{action_taken_by} fra %{date}, noe som var %{type}. De skrev:"
|
||||
next_steps: Du kan godkjenne anken for å angre på moderasjonsvedtaket eller ignorere det.
|
||||
subject: "%{username} anker en moderasjonsbeslutning for %{instance}"
|
||||
new_critical_software_updates:
|
||||
body: Nye kritiske versjoner av Mastodon har blitt utgitt, det kan være fordelaktig å oppdatere så snart som mulig!
|
||||
subject: Kritiske Mastodon-oppdateringer er tilgjengelige for %{instance}!
|
||||
|
@ -1161,19 +1161,19 @@
|
|||
disputes:
|
||||
strikes:
|
||||
action_taken: Handling utført
|
||||
appeal: Klage
|
||||
appeal_approved: Denne advarselens klage ble tatt til følge og er ikke lenger gyldig
|
||||
appeal_rejected: Klagen ble avvist
|
||||
appeal_submitted_at: Klage levert
|
||||
appealed_msg: Din klage har blitt levert. Du får beskjed om den blir godkjent.
|
||||
appeal: Anke
|
||||
appeal_approved: Denne advarselens anke ble tatt til følge og er ikke lenger gyldig
|
||||
appeal_rejected: Anken ble avvist
|
||||
appeal_submitted_at: Anke levert
|
||||
appealed_msg: Anken din har blitt levert. Du får beskjed om den blir godkjent.
|
||||
appeals:
|
||||
submit: Lever klage
|
||||
approve_appeal: Godkjenn klage
|
||||
submit: Lever anke
|
||||
approve_appeal: Godkjenn anke
|
||||
associated_report: Tilhørende rapport
|
||||
created_at: Datert
|
||||
description_html: Dette er tiltakene mot din konto og advarsler som har blitt sent til deg av %{instance}-personalet.
|
||||
recipient: Adressert til
|
||||
reject_appeal: Avvis klage
|
||||
reject_appeal: Avvis anke
|
||||
status: 'Innlegg #%{id}'
|
||||
status_removed: Innlegg allerede fjernet fra systemet
|
||||
title: "%{action} fra %{date}"
|
||||
|
@ -1185,9 +1185,9 @@
|
|||
sensitive: Merking av konto som sensitiv
|
||||
silence: Begrensning av konto
|
||||
suspend: Suspensjon av konto
|
||||
your_appeal_approved: Din klage har blitt godkjent
|
||||
your_appeal_pending: Du har levert en klage
|
||||
your_appeal_rejected: Din klage har blitt avvist
|
||||
your_appeal_approved: Anken din har blitt godkjent
|
||||
your_appeal_pending: Du har levert en anke
|
||||
your_appeal_rejected: Anken din har blitt avvist
|
||||
domain_validator:
|
||||
invalid_domain: er ikke et gyldig domenenavn
|
||||
edit_profile:
|
||||
|
@ -1608,6 +1608,7 @@
|
|||
unknown_browser: Ukjent Nettleser
|
||||
weibo: Weibo
|
||||
current_session: Nåværende økt
|
||||
date: Dato
|
||||
description: "%{browser} på %{platform}"
|
||||
explanation: Dette er nettlesere som er pålogget på din Mastodon-konto akkurat nå.
|
||||
ip: IP-adresse
|
||||
|
@ -1740,7 +1741,7 @@
|
|||
sensitive_content: Følsomt innhold
|
||||
strikes:
|
||||
errors:
|
||||
too_late: Det er for sent å klage på denne advarselen
|
||||
too_late: Det er for sent å anke denne advarselen
|
||||
tags:
|
||||
does_not_match_previous_name: samsvarer ikke med det forrige navnet
|
||||
themes:
|
||||
|
@ -1774,14 +1775,19 @@
|
|||
webauthn: Sikkerhetsnøkler
|
||||
user_mailer:
|
||||
appeal_approved:
|
||||
explanation: Klagen på advarselen mot din konto den %{strike_date} som du sendte inn den %{appeal_date} har blitt godkjent. Din konto er nok en gang i god stand.
|
||||
subject: Din klage fra %{date} er godkjent
|
||||
title: Klage godkjent
|
||||
action: Kontoinnstillinger
|
||||
explanation: Anken på advarselen mot din konto den %{strike_date} som du sendte inn den %{appeal_date} har blitt godkjent. Din konto er nok en gang i god stand.
|
||||
subject: Anken din fra %{date} er godkjent
|
||||
subtitle: Kontoen din er tilbake i god stand.
|
||||
title: Anke godkjent
|
||||
appeal_rejected:
|
||||
explanation: Klagen på advarselen mot din konto den %{strike_date} som du sendte inn den %{appeal_date} har blitt avvist.
|
||||
subject: Din klage fra %{date} er avvist
|
||||
title: Klage avvist
|
||||
explanation: Anken på advarselen mot din konto den %{strike_date} som du sendte inn den %{appeal_date} har blitt avvist.
|
||||
subject: Anken din fra %{date} er avvist
|
||||
subtitle: Anken din har blitt avvist.
|
||||
title: Anke avvist
|
||||
backup_ready:
|
||||
explanation: Du etterspurte en fullstendig sikkerhetskopi av din Mastodon-konto.
|
||||
extra: Den er nå klar for nedlasting!
|
||||
subject: Arkivet ditt er klart til å lastes ned
|
||||
title: Nedlasting av arkiv
|
||||
suspicious_sign_in:
|
||||
|
@ -1792,8 +1798,8 @@
|
|||
subject: Din konto ble tatt i bruk fra en ny IP-adresse
|
||||
title: En ny pålogging
|
||||
warning:
|
||||
appeal: Lever en klage
|
||||
appeal_description: Hvis du mener dette er feil, kan du sende inn en klage til personalet i %{instance}.
|
||||
appeal: Lever en anke
|
||||
appeal_description: Hvis du mener dette er feil, kan du sende inn en anke til personalet i %{instance}.
|
||||
categories:
|
||||
spam: Søppelpost
|
||||
violation: Innholdet bryter følgende retningslinjer for fellesskapet
|
||||
|
@ -1837,6 +1843,7 @@
|
|||
go_to_sso_account_settings: Gå til din identitetsleverandørs kontoinnstillinger
|
||||
invalid_otp_token: Ugyldig to-faktorkode
|
||||
otp_lost_help_html: Hvis du mistet tilgangen til begge deler, kan du komme i kontakt med %{email}
|
||||
rate_limited: For mange autentiseringsforsøk, prøv igjen senere.
|
||||
seamless_external_login: Du er logget inn via en ekstern tjeneste, så passord og e-post innstillinger er ikke tilgjengelige.
|
||||
signed_in_as: 'Innlogget som:'
|
||||
verification:
|
||||
|
|
|
@ -1907,6 +1907,7 @@ pl:
|
|||
go_to_sso_account_settings: Przejdź do ustawień konta dostawcy tożsamości
|
||||
invalid_otp_token: Kod uwierzytelniający jest niepoprawny
|
||||
otp_lost_help_html: Jeżeli utracisz dostęp do obu, możesz skontaktować się z %{email}
|
||||
rate_limited: Zbyt wiele prób uwierzytelnienia. Spróbuj ponownie później.
|
||||
seamless_external_login: Zalogowano z użyciem zewnętrznej usługi, więc ustawienia hasła i adresu e-mail nie są dostępne.
|
||||
signed_in_as: 'Zalogowano jako:'
|
||||
verification:
|
||||
|
|
|
@ -1843,6 +1843,7 @@ pt-PT:
|
|||
go_to_sso_account_settings: Ir para as definições de conta do seu fornecedor de identidade
|
||||
invalid_otp_token: Código de autenticação inválido
|
||||
otp_lost_help_html: Se perdeu o acesso a ambos, pode entrar em contacto com %{email}
|
||||
rate_limited: Demasiadas tentativas de autenticação, tente novamente mais tarde.
|
||||
seamless_external_login: Tu estás ligado via um serviço externo. Por isso, as configurações da palavra-passe e do e-mail não estão disponíveis.
|
||||
signed_in_as: 'Registado como:'
|
||||
verification:
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
starts_at: Valgfritt. I tilfellet din kunngjøring er bundet til en spesifikk tidsramme
|
||||
text: Du kan bruke innlegg-syntaks. Vennligst vær oppmerksom på plassen som kunngjøringen vil ta opp på brukeren sin skjerm
|
||||
appeal:
|
||||
text: Du kan kun klage på en advarsel en gang
|
||||
text: Du kan kun anke en advarsel en gang
|
||||
defaults:
|
||||
autofollow: Folk som lager en konto gjennom invitasjonen, vil automatisk følge deg
|
||||
avatar: PNG, GIF eller JPG. Maksimalt %{size}. Vil bli nedskalert til %{dimensions}px
|
||||
|
@ -282,7 +282,7 @@
|
|||
sign_up_requires_approval: Begrens påmeldinger
|
||||
severity: Oppføring
|
||||
notification_emails:
|
||||
appeal: Noen klager på en moderator sin avgjørelse
|
||||
appeal: Noen anker en moderator sin avgjørelse
|
||||
digest: Send sammendrag på e-post
|
||||
favourite: Send e-post når noen setter din status som favoritt
|
||||
follow: Send e-post når noen følger deg
|
||||
|
|
|
@ -633,6 +633,7 @@ sk:
|
|||
documentation_link: Zisti viac
|
||||
release_notes: Poznámky k vydaniu
|
||||
title: Dostupné aktualizácie
|
||||
type: Druh
|
||||
types:
|
||||
major: Hlavné vydanie
|
||||
patch: Opravné vydanie - opravy a jednoducho uplatniteľné zmeny
|
||||
|
@ -641,6 +642,7 @@ sk:
|
|||
account: Autor
|
||||
application: Aplikácia
|
||||
back_to_account: Späť na účet
|
||||
back_to_report: Späť na stránku hlásenia
|
||||
batch:
|
||||
remove_from_report: Vymaž z hlásenia
|
||||
report: Hlásenie
|
||||
|
@ -730,6 +732,7 @@ sk:
|
|||
new_appeal:
|
||||
actions:
|
||||
none: varovanie
|
||||
silence: obmedziť ich účet
|
||||
new_pending_account:
|
||||
body: Podrobnosti o novom účte sú uvedené nižšie. Môžeš túto registračnú požiadavku buď prijať, alebo zamietnúť.
|
||||
subject: Nový účet očakáva preverenie na %{instance} (%{username})
|
||||
|
@ -1277,6 +1280,7 @@ sk:
|
|||
follow_limit_reached: Nemôžeš následovať viac ako %{limit} ľudí
|
||||
invalid_otp_token: Neplatný kód pre dvojfaktorovú autentikáciu
|
||||
otp_lost_help_html: Pokiaľ si stratil/a prístup k obom, môžeš dať vedieť %{email}
|
||||
rate_limited: Príliš veľa pokusov o overenie, skús to znova neskôr.
|
||||
seamless_external_login: Si prihlásená/ý cez externú službu, takže nastavenia hesla a emailu ti niesú prístupné.
|
||||
signed_in_as: 'Prihlásená/ý ako:'
|
||||
verification:
|
||||
|
|
|
@ -1907,6 +1907,7 @@ sl:
|
|||
go_to_sso_account_settings: Pojdite na nastavitve svojega računa ponudnika identitete
|
||||
invalid_otp_token: Neveljavna dvofaktorska koda
|
||||
otp_lost_help_html: Če ste izgubili dostop do obeh, stopite v stik z %{email}
|
||||
rate_limited: Preveč poskusov preverjanja pristnosti, poskusite kasneje.
|
||||
seamless_external_login: Prijavljeni ste prek zunanje storitve, tako da nastavitve gesla in e-pošte niso na voljo.
|
||||
signed_in_as: 'Vpisani kot:'
|
||||
verification:
|
||||
|
|
|
@ -1875,6 +1875,7 @@ sr-Latn:
|
|||
go_to_sso_account_settings: Idite na podešavanja naloga svog dobavljača identiteta
|
||||
invalid_otp_token: Neispravni dvofaktorski kod
|
||||
otp_lost_help_html: Ako izgubite pristup za oba, možete stupiti u kontakt sa %{email}
|
||||
rate_limited: Previše pokušaja autentifikacije, pokušajte ponovo kasnije.
|
||||
seamless_external_login: Prijavljeni ste putem spoljašnje usluge, tako da lozinka i podešavanja E-pošte nisu dostupni.
|
||||
signed_in_as: 'Prijavljen/a kao:'
|
||||
verification:
|
||||
|
|
|
@ -1875,6 +1875,7 @@ sr:
|
|||
go_to_sso_account_settings: Идите на подешавања налога свог добављача идентитета
|
||||
invalid_otp_token: Неисправни двофакторски код
|
||||
otp_lost_help_html: Ако изгубите приступ за оба, можете ступити у контакт са %{email}
|
||||
rate_limited: Превише покушаја аутентификације, покушајте поново касније.
|
||||
seamless_external_login: Пријављени сте путем спољашње услуге, тако да лозинка и подешавања Е-поште нису доступни.
|
||||
signed_in_as: 'Пријављен/а као:'
|
||||
verification:
|
||||
|
|
|
@ -1842,6 +1842,7 @@ sv:
|
|||
go_to_sso_account_settings: Gå till din identitetsleverantörs kontoinställningar
|
||||
invalid_otp_token: Ogiltig tvåfaktorskod
|
||||
otp_lost_help_html: Om du förlorat åtkomst till båda kan du komma i kontakt med %{email}
|
||||
rate_limited: För många autentiseringsförsök, försök igen senare.
|
||||
seamless_external_login: Du är inloggad via en extern tjänst, inställningar för lösenord och e-post är därför inte tillgängliga.
|
||||
signed_in_as: 'Inloggad som:'
|
||||
verification:
|
||||
|
|
|
@ -847,7 +847,7 @@ th:
|
|||
message_html: ไม่มีกระบวนการ Sidekiq ที่กำลังทำงานสำหรับคิว %{value} โปรดตรวจทานการกำหนดค่า Sidekiq ของคุณ
|
||||
software_version_critical_check:
|
||||
action: ดูการอัปเดตที่พร้อมใช้งาน
|
||||
message_html: มีการอัปเดต Mastodon สำคัญพร้อมใช้งาน โปรดอัปเดตโดยเร็วที่สุดเท่าที่จะทำได้
|
||||
message_html: มีการอัปเดต Mastodon สำคัญพร้อมใช้งาน โปรดอัปเดตโดยเร็วที่สุดเท่าที่จะเป็นไปได้
|
||||
software_version_patch_check:
|
||||
action: ดูการอัปเดตที่พร้อมใช้งาน
|
||||
message_html: มีการอัปเดต Mastodon ที่แก้ไขข้อบกพร่องพร้อมใช้งาน
|
||||
|
@ -961,7 +961,7 @@ th:
|
|||
next_steps: คุณสามารถอนุมัติการอุทธรณ์เพื่อเลิกทำการตัดสินใจในการควบคุม หรือเพิกเฉยต่อการอุทธรณ์
|
||||
subject: "%{username} กำลังอุทธรณ์การตัดสินใจในการควบคุมใน %{instance}"
|
||||
new_critical_software_updates:
|
||||
body: มีการปล่อยรุ่น Mastodon สำคัญใหม่ คุณอาจต้องการอัปเดตโดยเร็วที่สุดเท่าที่จะทำได้!
|
||||
body: มีการปล่อยรุ่น Mastodon สำคัญใหม่ คุณอาจต้องการอัปเดตโดยเร็วที่สุดเท่าที่จะเป็นไปได้!
|
||||
subject: การอัปเดต Mastodon สำคัญพร้อมใช้งานสำหรับ %{instance}!
|
||||
new_pending_account:
|
||||
body: รายละเอียดของบัญชีใหม่อยู่ด้านล่าง คุณสามารถอนุมัติหรือปฏิเสธใบสมัครนี้
|
||||
|
@ -1582,6 +1582,7 @@ th:
|
|||
unknown_browser: เบราว์เซอร์ที่ไม่รู้จัก
|
||||
weibo: Weibo
|
||||
current_session: เซสชันปัจจุบัน
|
||||
date: วันที่
|
||||
description: "%{browser} ใน %{platform}"
|
||||
explanation: นี่คือเว็บเบราว์เซอร์ที่เข้าสู่ระบบบัญชี Mastodon ของคุณในปัจจุบัน
|
||||
ip: IP
|
||||
|
@ -1742,14 +1743,19 @@ th:
|
|||
webauthn: กุญแจความปลอดภัย
|
||||
user_mailer:
|
||||
appeal_approved:
|
||||
action: การตั้งค่าบัญชี
|
||||
explanation: อนุมัติการอุทธรณ์การดำเนินการต่อบัญชีของคุณเมื่อ %{strike_date} ที่คุณได้ส่งเมื่อ %{appeal_date} แล้ว บัญชีของคุณอยู่ในสถานะที่ดีอีกครั้งหนึ่ง
|
||||
subject: อนุมัติการอุทธรณ์ของคุณจาก %{date} แล้ว
|
||||
subtitle: บัญชีของคุณอยู่ในสถานะที่ดีอีกครั้งหนึ่ง
|
||||
title: อนุมัติการอุทธรณ์แล้ว
|
||||
appeal_rejected:
|
||||
explanation: ปฏิเสธการอุทธรณ์การดำเนินการต่อบัญชีของคุณเมื่อ %{strike_date} ที่คุณได้ส่งเมื่อ %{appeal_date} แล้ว
|
||||
subject: ปฏิเสธการอุทธรณ์ของคุณจาก %{date} แล้ว
|
||||
subtitle: ปฏิเสธการอุทธรณ์ของคุณแล้ว
|
||||
title: ปฏิเสธการอุทธรณ์แล้ว
|
||||
backup_ready:
|
||||
explanation: คุณได้ขอข้อมูลสำรองแบบเต็มของบัญชี Mastodon ของคุณ
|
||||
extra: ตอนนี้ข้อมูลสำรองพร้อมสำหรับการดาวน์โหลดแล้ว!
|
||||
subject: การเก็บถาวรของคุณพร้อมสำหรับการดาวน์โหลดแล้ว
|
||||
title: การส่งออกการเก็บถาวร
|
||||
suspicious_sign_in:
|
||||
|
@ -1805,6 +1811,7 @@ th:
|
|||
go_to_sso_account_settings: ไปยังการตั้งค่าบัญชีของผู้ให้บริการข้อมูลประจำตัวของคุณ
|
||||
invalid_otp_token: รหัสสองปัจจัยไม่ถูกต้อง
|
||||
otp_lost_help_html: หากคุณสูญเสียการเข้าถึงทั้งสองอย่าง คุณสามารถติดต่อ %{email}
|
||||
rate_limited: มีความพยายามในการรับรองความถูกต้องมากเกินไป ลองอีกครั้งในภายหลัง
|
||||
seamless_external_login: คุณได้เข้าสู่ระบบผ่านบริการภายนอก ดังนั้นจึงไม่มีการตั้งค่ารหัสผ่านและอีเมล
|
||||
signed_in_as: 'ลงชื่อเข้าเป็น:'
|
||||
verification:
|
||||
|
|
|
@ -1843,6 +1843,7 @@ tr:
|
|||
go_to_sso_account_settings: Kimlik sağlayıcı hesap ayarlarına gidin
|
||||
invalid_otp_token: Geçersiz iki adımlı doğrulama kodu
|
||||
otp_lost_help_html: Her ikisine de erişiminizi kaybettiyseniz, %{email} ile irtibata geçebilirsiniz
|
||||
rate_limited: Çok fazla kimlik doğrulama denemesi. Daha sonra tekrar deneyin.
|
||||
seamless_external_login: Harici bir servis aracılığıyla oturum açtınız, bu nedenle parola ve e-posta ayarları mevcut değildir.
|
||||
signed_in_as: 'Oturum açtı:'
|
||||
verification:
|
||||
|
|
|
@ -1903,6 +1903,7 @@ uk:
|
|||
go_to_sso_account_settings: Перейдіть до налаштувань облікового запису постачальника ідентифікації
|
||||
invalid_otp_token: Введено неправильний код
|
||||
otp_lost_help_html: Якщо ви втратили доступ до обох, ви можете отримати доступ з %{email}
|
||||
rate_limited: Занадто багато спроб з'єднання. Спробуйте ще раз пізніше.
|
||||
seamless_external_login: Ви увійшли за допомогою зовнішнього сервісу, тому налаштування паролю та електронної пошти недоступні.
|
||||
signed_in_as: 'Ви увійшли як:'
|
||||
verification:
|
||||
|
|
|
@ -1811,6 +1811,7 @@ vi:
|
|||
go_to_sso_account_settings: Thiết lập tài khoản nhà cung cấp danh tính
|
||||
invalid_otp_token: Mã xác minh 2 bước không hợp lệ
|
||||
otp_lost_help_html: Nếu bạn mất quyền truy cập vào cả hai, bạn có thể đăng nhập bằng %{email}
|
||||
rate_limited: Quá nhiều lần thử, vui lòng thử lại sau.
|
||||
seamless_external_login: Bạn đã đăng nhập thông qua một dịch vụ bên ngoài, vì vậy mật khẩu và email không khả dụng.
|
||||
signed_in_as: 'Đăng nhập bằng:'
|
||||
verification:
|
||||
|
|
|
@ -1811,6 +1811,7 @@ zh-CN:
|
|||
go_to_sso_account_settings: 转到您的身份提供商进行账户设置
|
||||
invalid_otp_token: 输入的双因素认证代码无效
|
||||
otp_lost_help_html: 如果你不慎丢失了所有的代码,请联系 %{email} 寻求帮助
|
||||
rate_limited: 验证尝试次数过多,请稍后再试。
|
||||
seamless_external_login: 因为你是通过外部服务登录的,所以密码和电子邮件地址设置都不可用。
|
||||
signed_in_as: 当前登录的账户:
|
||||
verification:
|
||||
|
|
|
@ -1811,6 +1811,7 @@ zh-HK:
|
|||
go_to_sso_account_settings: 前往你身份提供者的帳號設定
|
||||
invalid_otp_token: 雙重認證碼不正確
|
||||
otp_lost_help_html: 如果這兩者你均無法登入,你可以聯繫 %{email}
|
||||
rate_limited: 嘗試認證次數太多,請稍後再試。
|
||||
seamless_external_login: 因為你正在使用第三方服務登入,所以不能設定密碼和電郵。
|
||||
signed_in_as: 目前登入的帳戶:
|
||||
verification:
|
||||
|
|
|
@ -1813,6 +1813,7 @@ zh-TW:
|
|||
go_to_sso_account_settings: 前往您的身分提供商 (identity provider) 之帳號設定
|
||||
invalid_otp_token: 兩階段認證碼不正確
|
||||
otp_lost_help_html: 如果您無法存取這兩者,您可以透過 %{email} 與我們聯繫
|
||||
rate_limited: 身份驗證嘗試太多次,請稍後再試。
|
||||
seamless_external_login: 由於您是由外部系統登入,所以不能設定密碼與電子郵件。
|
||||
signed_in_as: 目前登入的帳號:
|
||||
verification:
|
||||
|
|
128
config/templates/privacy-policy.md
Normal file
128
config/templates/privacy-policy.md
Normal file
|
@ -0,0 +1,128 @@
|
|||
This privacy policy describes how %{domain}s ("%{domain}s", "we", "us")
|
||||
collects, protects and uses the personally identifiable information you may
|
||||
provide through the %{domain}s website or its API. The policy also
|
||||
describes the choices available to you regarding our use of your personal
|
||||
information and how you can access and update this information. This policy
|
||||
does not apply to the practices of companies that %{domain}s does not own
|
||||
or control, or to individuals that %{domain}s does not employ or manage.
|
||||
|
||||
# What information do we collect?
|
||||
|
||||
- **Basic account information**: If you register on this server, you may be
|
||||
asked to enter a username, an e-mail address and a password. You may also
|
||||
enter additional profile information such as a display name and biography, and
|
||||
upload a profile picture and header image. The username, display name,
|
||||
biography, profile picture and header image are always listed publicly.
|
||||
- **Posts, following and other public information**: The list of people you
|
||||
follow is listed publicly, the same is true for your followers. When you
|
||||
submit a message, the date and time is stored as well as the application you
|
||||
submitted the message from. Messages may contain media attachments, such as
|
||||
pictures and videos. Public and unlisted posts are available publicly. When
|
||||
you feature a post on your profile, that is also publicly available
|
||||
information. Your posts are delivered to your followers, in some cases it
|
||||
means they are delivered to different servers and copies are stored there.
|
||||
When you delete posts, this is likewise delivered to your followers. The
|
||||
action of reblogging or favouriting another post is always public.
|
||||
- **Direct and followers-only posts**: All posts are stored and processed on the
|
||||
server. Followers-only posts are delivered to your followers and users who are
|
||||
mentioned in them, and direct posts are delivered only to users mentioned in
|
||||
them. In some cases it means they are delivered to different servers and
|
||||
copies are stored there. We make a good faith effort to limit the access to
|
||||
those posts only to authorized persons, but other servers may fail to do so.
|
||||
Therefore it's important to review servers your followers belong to. You may
|
||||
toggle an option to approve and reject new followers manually in the settings.
|
||||
**Please keep in mind that the operators of the server and any receiving
|
||||
server may view such messages**, and that recipients may screenshot, copy or
|
||||
otherwise re-share them. **Do not share any sensitive information over
|
||||
Mastodon.**
|
||||
- **IPs and other metadata**: When you log in, we record the IP address you log
|
||||
in from, as well as the name of your browser application. All the logged in
|
||||
sessions are available for your review and revocation in the settings. The
|
||||
latest IP address used is stored for up to 12 months. We also may retain
|
||||
server logs which include the IP address of every request to our server.
|
||||
|
||||
# What do we use your information for?
|
||||
|
||||
Any of the information we collect from you may be used in the following ways:
|
||||
|
||||
- To provide the core functionality of Mastodon. You can only interact with
|
||||
other people's content and post your own content when you are logged in. For
|
||||
example, you may follow other people to view their combined posts in your own
|
||||
personalized home timeline.
|
||||
- To aid moderation of the community, for example comparing your IP address with
|
||||
other known ones to determine ban evasion or other violations.
|
||||
- The email address you provide may be used to send you information,
|
||||
notifications about other people interacting with your content or sending you
|
||||
messages, and to respond to inquiries, and/or other requests or questions.
|
||||
|
||||
# How do we protect your information?
|
||||
|
||||
We implement a variety of security measures to maintain the safety of your
|
||||
personal information when you enter, submit, or access your personal
|
||||
information. Among other things, your browser session, as well as the traffic
|
||||
between your applications and the API, are secured with SSL, and your password
|
||||
is hashed using a strong one-way algorithm. You may enable two-factor
|
||||
authentication to further secure access to your account.
|
||||
|
||||
# What is our data retention policy?
|
||||
|
||||
We will make a good faith effort to:
|
||||
|
||||
- Retain server logs containing the IP address of all requests to this server,
|
||||
in so far as such logs are kept, no more than 90 days.
|
||||
- Retain the IP addresses associated with registered users no more than 12
|
||||
months.
|
||||
|
||||
You can request and download an archive of your content, including your posts,
|
||||
media attachments, profile picture, and header image.
|
||||
|
||||
You may irreversibly delete your account at any time.
|
||||
|
||||
# Do we use cookies?
|
||||
|
||||
Yes. Cookies are small files that a site or its service provider transfers to
|
||||
your computer's hard drive through your Web browser (if you allow). These
|
||||
cookies enable the site to recognize your browser and, if you have a registered
|
||||
account, associate it with your registered account.
|
||||
|
||||
We use cookies to understand and save your preferences for future visits.
|
||||
|
||||
# Do we disclose any information to outside parties?
|
||||
|
||||
We do not sell, trade, or otherwise transfer to outside parties your personally
|
||||
identifiable information. This does not include trusted third parties who assist
|
||||
us in operating our site, conducting our business, or servicing you, so long as
|
||||
those parties agree to keep this information confidential. We may also release
|
||||
your information when we believe release is appropriate to comply with the law,
|
||||
enforce our site policies, or protect ours or others rights, property, or
|
||||
safety.
|
||||
|
||||
Your public content may be downloaded by other servers in the network. Your
|
||||
public and followers-only posts are delivered to the servers where your
|
||||
followers reside, and direct messages are delivered to the servers of the
|
||||
recipients, in so far as those followers or recipients reside on a different
|
||||
server than this.
|
||||
|
||||
When you authorize an application to use your account, depending on the scope of
|
||||
permissions you approve, it may access your public profile information, your
|
||||
following list, your followers, your lists, all your posts, and your favourites.
|
||||
Applications can never access your e-mail address or password.
|
||||
|
||||
# Site usage by children
|
||||
|
||||
If this server is in the EU or the EEA: Our site, products and services are all
|
||||
directed to people who are at least 16 years old. If you are under the age of
|
||||
16, per the requirements of the GDPR (General Data Protection Regulation) do not
|
||||
use this site.
|
||||
|
||||
If this server is in the USA: Our site, products and services are all directed
|
||||
to people who are at least 13 years old. If you are under the age of 13, per the
|
||||
requirements of COPPA (Children's Online Privacy Protection Act) do not use this
|
||||
site.
|
||||
|
||||
Law requirements can be different if this server is in another jurisdiction.
|
||||
|
||||
---
|
||||
|
||||
This document is CC-BY-SA. Originally adapted from the [Discourse privacy
|
||||
policy](https://github.com/discourse/discourse).
|
|
@ -16,7 +16,7 @@ module Paperclip
|
|||
private
|
||||
|
||||
def cache_current_values
|
||||
@original_filename = filename_from_content_disposition.presence || filename_from_path.presence || 'data'
|
||||
@original_filename = truncated_filename
|
||||
@tempfile = copy_to_tempfile(@target)
|
||||
@content_type = ContentTypeDetector.new(@tempfile.path).detect
|
||||
@size = File.size(@tempfile)
|
||||
|
@ -43,6 +43,13 @@ module Paperclip
|
|||
source.response.connection.close
|
||||
end
|
||||
|
||||
def truncated_filename
|
||||
filename = filename_from_content_disposition.presence || filename_from_path.presence || 'data'
|
||||
extension = File.extname(filename)
|
||||
basename = File.basename(filename, extension)
|
||||
[basename[...20], extension[..4]].compact_blank.join
|
||||
end
|
||||
|
||||
def filename_from_content_disposition
|
||||
disposition = @target.response.headers['content-disposition']
|
||||
disposition&.match(/filename="([^"]*)"/)&.captures&.first
|
||||
|
|
|
@ -16,8 +16,8 @@ namespace :db do
|
|||
end
|
||||
|
||||
task pre_migration_check: :environment do
|
||||
version = ActiveRecord::Base.connection.select_one("SELECT current_setting('server_version_num') AS v")['v'].to_i
|
||||
abort 'This version of Mastodon requires PostgreSQL 9.5 or newer. Please update PostgreSQL before updating Mastodon' if version < 90_500
|
||||
version = ActiveRecord::Base.connection.database_version
|
||||
abort 'This version of Mastodon requires PostgreSQL 12.0 or newer. Please update PostgreSQL before updating Mastodon.' if version < 120_000
|
||||
end
|
||||
|
||||
Rake::Task['db:migrate'].enhance(['db:pre_migration_check'])
|
||||
|
|
|
@ -262,6 +262,40 @@ RSpec.describe Auth::SessionsController do
|
|||
end
|
||||
end
|
||||
|
||||
context 'when repeatedly using an invalid TOTP code before using a valid code' do
|
||||
before do
|
||||
stub_const('Auth::SessionsController::MAX_2FA_ATTEMPTS_PER_HOUR', 2)
|
||||
|
||||
# Travel to the beginning of an hour to avoid crossing rate-limit buckets
|
||||
travel_to '2023-12-20T10:00:00Z'
|
||||
end
|
||||
|
||||
it 'does not log the user in' do
|
||||
Auth::SessionsController::MAX_2FA_ATTEMPTS_PER_HOUR.times do
|
||||
post :create, params: { user: { otp_attempt: '1234' } }, session: { attempt_user_id: user.id, attempt_user_updated_at: user.updated_at.to_s }
|
||||
expect(controller.current_user).to be_nil
|
||||
end
|
||||
|
||||
post :create, params: { user: { otp_attempt: user.current_otp } }, session: { attempt_user_id: user.id, attempt_user_updated_at: user.updated_at.to_s }
|
||||
|
||||
expect(controller.current_user).to be_nil
|
||||
expect(flash[:alert]).to match I18n.t('users.rate_limited')
|
||||
end
|
||||
|
||||
it 'sends a suspicious sign-in mail', :sidekiq_inline do
|
||||
Auth::SessionsController::MAX_2FA_ATTEMPTS_PER_HOUR.times do
|
||||
post :create, params: { user: { otp_attempt: '1234' } }, session: { attempt_user_id: user.id, attempt_user_updated_at: user.updated_at.to_s }
|
||||
expect(controller.current_user).to be_nil
|
||||
end
|
||||
|
||||
post :create, params: { user: { otp_attempt: user.current_otp } }, session: { attempt_user_id: user.id, attempt_user_updated_at: user.updated_at.to_s }
|
||||
|
||||
expect(UserMailer.deliveries.size).to eq(1)
|
||||
expect(UserMailer.deliveries.first.to.first).to eq(user.email)
|
||||
expect(UserMailer.deliveries.first.subject).to eq(I18n.t('user_mailer.failed_2fa.subject'))
|
||||
end
|
||||
end
|
||||
|
||||
context 'when using a valid OTP' do
|
||||
before do
|
||||
post :create, params: { user: { otp_attempt: user.current_otp } }, session: { attempt_user_id: user.id, attempt_user_updated_at: user.updated_at.to_s }
|
||||
|
|
|
@ -93,4 +93,9 @@ class UserMailerPreview < ActionMailer::Preview
|
|||
def suspicious_sign_in
|
||||
UserMailer.suspicious_sign_in(User.first, '127.0.0.1', 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:75.0) Gecko/20100101 Firefox/75.0', Time.now.utc)
|
||||
end
|
||||
|
||||
# Preview this email at http://localhost:3000/rails/mailers/user_mailer/failed_2fa
|
||||
def failed_2fa
|
||||
UserMailer.failed_2fa(User.first, '127.0.0.1', 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:75.0) Gecko/20100101 Firefox/75.0', Time.now.utc)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -135,6 +135,24 @@ describe UserMailer do
|
|||
'user_mailer.suspicious_sign_in.subject'
|
||||
end
|
||||
|
||||
describe '#failed_2fa' do
|
||||
let(:ip) { '192.168.0.1' }
|
||||
let(:agent) { 'NCSA_Mosaic/2.0 (Windows 3.1)' }
|
||||
let(:timestamp) { Time.now.utc }
|
||||
let(:mail) { described_class.failed_2fa(receiver, ip, agent, timestamp) }
|
||||
|
||||
it 'renders failed 2FA notification' do
|
||||
receiver.update!(locale: nil)
|
||||
|
||||
expect(mail)
|
||||
.to be_present
|
||||
.and(have_body_text(I18n.t('user_mailer.failed_2fa.explanation')))
|
||||
end
|
||||
|
||||
include_examples 'localized subject',
|
||||
'user_mailer.failed_2fa.subject'
|
||||
end
|
||||
|
||||
describe '#appeal_approved' do
|
||||
let(:appeal) { Fabricate(:appeal, account: receiver.account, approved_at: Time.now.utc) }
|
||||
let(:mail) { described_class.appeal_approved(receiver, appeal) }
|
||||
|
|
|
@ -835,6 +835,50 @@ RSpec.describe Account do
|
|||
end
|
||||
|
||||
describe 'scopes' do
|
||||
describe 'matches_uri_prefix' do
|
||||
let!(:alice) { Fabricate :account, domain: 'host.example', uri: 'https://host.example/user/a' }
|
||||
let!(:bob) { Fabricate :account, domain: 'top-level.example', uri: 'https://top-level.example' }
|
||||
|
||||
it 'returns accounts which start with the value' do
|
||||
results = described_class.matches_uri_prefix('https://host.example')
|
||||
|
||||
expect(results.size)
|
||||
.to eq(1)
|
||||
expect(results)
|
||||
.to include(alice)
|
||||
.and not_include(bob)
|
||||
end
|
||||
|
||||
it 'returns accounts which equal the value' do
|
||||
results = described_class.matches_uri_prefix('https://top-level.example')
|
||||
|
||||
expect(results.size)
|
||||
.to eq(1)
|
||||
expect(results)
|
||||
.to include(bob)
|
||||
.and not_include(alice)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'auditable' do
|
||||
let!(:alice) { Fabricate :account }
|
||||
let!(:bob) { Fabricate :account }
|
||||
|
||||
before do
|
||||
2.times { Fabricate :action_log, account: alice }
|
||||
end
|
||||
|
||||
it 'returns distinct accounts with action log records' do
|
||||
results = described_class.auditable
|
||||
|
||||
expect(results.size)
|
||||
.to eq(1)
|
||||
expect(results)
|
||||
.to include(alice)
|
||||
.and not_include(bob)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'alphabetic' do
|
||||
it 'sorts by alphabetic order of domain and username' do
|
||||
matches = [
|
||||
|
|
|
@ -2,11 +2,11 @@
|
|||
|
||||
require 'rails_helper'
|
||||
|
||||
describe Api::V1::Accounts::FollowerAccountsController do
|
||||
render_views
|
||||
|
||||
describe 'API V1 Accounts FollowerAccounts' do
|
||||
let(:user) { Fabricate(:user) }
|
||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'read:accounts') }
|
||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
|
||||
let(:scopes) { 'read:accounts' }
|
||||
let(:headers) { { 'Authorization' => "Bearer #{token.token}" } }
|
||||
let(:account) { Fabricate(:account) }
|
||||
let(:alice) { Fabricate(:account) }
|
||||
let(:bob) { Fabricate(:account) }
|
||||
|
@ -14,12 +14,11 @@ describe Api::V1::Accounts::FollowerAccountsController do
|
|||
before do
|
||||
alice.follow!(account)
|
||||
bob.follow!(account)
|
||||
allow(controller).to receive(:doorkeeper_token) { token }
|
||||
end
|
||||
|
||||
describe 'GET #index' do
|
||||
describe 'GET /api/v1/accounts/:acount_id/followers' do
|
||||
it 'returns accounts following the given account', :aggregate_failures do
|
||||
get :index, params: { account_id: account.id, limit: 2 }
|
||||
get "/api/v1/accounts/#{account.id}/followers", params: { limit: 2 }, headers: headers
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
expect(body_as_json.size).to eq 2
|
||||
|
@ -28,7 +27,7 @@ describe Api::V1::Accounts::FollowerAccountsController do
|
|||
|
||||
it 'does not return blocked users', :aggregate_failures do
|
||||
user.account.block!(bob)
|
||||
get :index, params: { account_id: account.id, limit: 2 }
|
||||
get "/api/v1/accounts/#{account.id}/followers", params: { limit: 2 }, headers: headers
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
expect(body_as_json.size).to eq 1
|
||||
|
@ -41,7 +40,7 @@ describe Api::V1::Accounts::FollowerAccountsController do
|
|||
end
|
||||
|
||||
it 'hides results' do
|
||||
get :index, params: { account_id: account.id, limit: 2 }
|
||||
get "/api/v1/accounts/#{account.id}/followers", params: { limit: 2 }, headers: headers
|
||||
expect(body_as_json.size).to eq 0
|
||||
end
|
||||
end
|
||||
|
@ -51,7 +50,7 @@ describe Api::V1::Accounts::FollowerAccountsController do
|
|||
|
||||
it 'returns all accounts, including muted accounts' do
|
||||
account.mute!(bob)
|
||||
get :index, params: { account_id: account.id, limit: 2 }
|
||||
get "/api/v1/accounts/#{account.id}/followers", params: { limit: 2 }, headers: headers
|
||||
|
||||
expect(body_as_json.size).to eq 2
|
||||
expect([body_as_json[0][:id], body_as_json[1][:id]]).to contain_exactly(alice.id.to_s, bob.id.to_s)
|
|
@ -2,11 +2,11 @@
|
|||
|
||||
require 'rails_helper'
|
||||
|
||||
describe Api::V1::Accounts::FollowingAccountsController do
|
||||
render_views
|
||||
|
||||
describe 'API V1 Accounts FollowingAccounts' do
|
||||
let(:user) { Fabricate(:user) }
|
||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'read:accounts') }
|
||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
|
||||
let(:scopes) { 'read:accounts' }
|
||||
let(:headers) { { 'Authorization' => "Bearer #{token.token}" } }
|
||||
let(:account) { Fabricate(:account) }
|
||||
let(:alice) { Fabricate(:account) }
|
||||
let(:bob) { Fabricate(:account) }
|
||||
|
@ -14,12 +14,11 @@ describe Api::V1::Accounts::FollowingAccountsController do
|
|||
before do
|
||||
account.follow!(alice)
|
||||
account.follow!(bob)
|
||||
allow(controller).to receive(:doorkeeper_token) { token }
|
||||
end
|
||||
|
||||
describe 'GET #index' do
|
||||
describe 'GET /api/v1/accounts/:account_id/following' do
|
||||
it 'returns accounts followed by the given account', :aggregate_failures do
|
||||
get :index, params: { account_id: account.id, limit: 2 }
|
||||
get "/api/v1/accounts/#{account.id}/following", params: { limit: 2 }, headers: headers
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
expect(body_as_json.size).to eq 2
|
||||
|
@ -28,7 +27,7 @@ describe Api::V1::Accounts::FollowingAccountsController do
|
|||
|
||||
it 'does not return blocked users', :aggregate_failures do
|
||||
user.account.block!(bob)
|
||||
get :index, params: { account_id: account.id, limit: 2 }
|
||||
get "/api/v1/accounts/#{account.id}/following", params: { limit: 2 }, headers: headers
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
expect(body_as_json.size).to eq 1
|
||||
|
@ -41,7 +40,7 @@ describe Api::V1::Accounts::FollowingAccountsController do
|
|||
end
|
||||
|
||||
it 'hides results' do
|
||||
get :index, params: { account_id: account.id, limit: 2 }
|
||||
get "/api/v1/accounts/#{account.id}/following", params: { limit: 2 }, headers: headers
|
||||
expect(body_as_json.size).to eq 0
|
||||
end
|
||||
end
|
||||
|
@ -51,7 +50,7 @@ describe Api::V1::Accounts::FollowingAccountsController do
|
|||
|
||||
it 'returns all accounts, including muted accounts' do
|
||||
account.mute!(bob)
|
||||
get :index, params: { account_id: account.id, limit: 2 }
|
||||
get "/api/v1/accounts/#{account.id}/following", params: { limit: 2 }, headers: headers
|
||||
|
||||
expect(body_as_json.size).to eq 2
|
||||
expect([body_as_json[0][:id], body_as_json[1][:id]]).to contain_exactly(alice.id.to_s, bob.id.to_s)
|
|
@ -2,21 +2,21 @@
|
|||
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe Api::V1::Statuses::FavouritedByAccountsController do
|
||||
render_views
|
||||
|
||||
let(:user) { Fabricate(:user) }
|
||||
let(:app) { Fabricate(:application, name: 'Test app', website: 'http://testapp.com') }
|
||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, application: app, scopes: 'read:accounts') }
|
||||
RSpec.describe 'API V1 Statuses Favourited by Accounts' do
|
||||
let(:user) { Fabricate(:user) }
|
||||
let(:scopes) { 'read:accounts' }
|
||||
# let(:app) { Fabricate(:application, name: 'Test app', website: 'http://testapp.com') }
|
||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
|
||||
let(:headers) { { 'Authorization' => "Bearer #{token.token}" } }
|
||||
let(:alice) { Fabricate(:account) }
|
||||
let(:bob) { Fabricate(:account) }
|
||||
|
||||
context 'with an oauth token' do
|
||||
before do
|
||||
allow(controller).to receive(:doorkeeper_token) { token }
|
||||
subject do
|
||||
get "/api/v1/statuses/#{status.id}/favourited_by", headers: headers, params: { limit: 2 }
|
||||
end
|
||||
|
||||
describe 'GET #index' do
|
||||
describe 'GET /api/v1/statuses/:status_id/favourited_by' do
|
||||
let(:status) { Fabricate(:status, account: user.account) }
|
||||
|
||||
before do
|
||||
|
@ -24,30 +24,38 @@ RSpec.describe Api::V1::Statuses::FavouritedByAccountsController do
|
|||
Favourite.create!(account: bob, status: status)
|
||||
end
|
||||
|
||||
it 'returns http success' do
|
||||
get :index, params: { status_id: status.id, limit: 2 }
|
||||
expect(response).to have_http_status(200)
|
||||
expect(response.headers['Link'].links.size).to eq(2)
|
||||
end
|
||||
it 'returns http success and accounts who favourited the status' do
|
||||
subject
|
||||
|
||||
it 'returns accounts who favorited the status' do
|
||||
get :index, params: { status_id: status.id, limit: 2 }
|
||||
expect(body_as_json.size).to eq 2
|
||||
expect([body_as_json[0][:id], body_as_json[1][:id]]).to contain_exactly(alice.id.to_s, bob.id.to_s)
|
||||
expect(response)
|
||||
.to have_http_status(200)
|
||||
expect(response.headers['Link'].links.size)
|
||||
.to eq(2)
|
||||
|
||||
expect(body_as_json.size)
|
||||
.to eq(2)
|
||||
expect(body_as_json)
|
||||
.to contain_exactly(
|
||||
include(id: alice.id.to_s),
|
||||
include(id: bob.id.to_s)
|
||||
)
|
||||
end
|
||||
|
||||
it 'does not return blocked users' do
|
||||
user.account.block!(bob)
|
||||
get :index, params: { status_id: status.id, limit: 2 }
|
||||
expect(body_as_json.size).to eq 1
|
||||
expect(body_as_json[0][:id]).to eq alice.id.to_s
|
||||
|
||||
subject
|
||||
|
||||
expect(body_as_json.size)
|
||||
.to eq 1
|
||||
expect(body_as_json.first[:id]).to eq(alice.id.to_s)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'without an oauth token' do
|
||||
before do
|
||||
allow(controller).to receive(:doorkeeper_token).and_return(nil)
|
||||
subject do
|
||||
get "/api/v1/statuses/#{status.id}/favourited_by", params: { limit: 2 }
|
||||
end
|
||||
|
||||
context 'with a private status' do
|
||||
|
@ -59,7 +67,8 @@ RSpec.describe Api::V1::Statuses::FavouritedByAccountsController do
|
|||
end
|
||||
|
||||
it 'returns http unauthorized' do
|
||||
get :index, params: { status_id: status.id }
|
||||
subject
|
||||
|
||||
expect(response).to have_http_status(404)
|
||||
end
|
||||
end
|
||||
|
@ -74,7 +83,8 @@ RSpec.describe Api::V1::Statuses::FavouritedByAccountsController do
|
|||
end
|
||||
|
||||
it 'returns http success' do
|
||||
get :index, params: { status_id: status.id }
|
||||
subject
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
end
|
|
@ -2,21 +2,20 @@
|
|||
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe Api::V1::Statuses::RebloggedByAccountsController do
|
||||
render_views
|
||||
|
||||
let(:user) { Fabricate(:user) }
|
||||
let(:app) { Fabricate(:application, name: 'Test app', website: 'http://testapp.com') }
|
||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, application: app, scopes: 'read:accounts') }
|
||||
RSpec.describe 'API V1 Statuses Reblogged by Accounts' do
|
||||
let(:user) { Fabricate(:user) }
|
||||
let(:scopes) { 'read:accounts' }
|
||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
|
||||
let(:headers) { { 'Authorization' => "Bearer #{token.token}" } }
|
||||
let(:alice) { Fabricate(:account) }
|
||||
let(:bob) { Fabricate(:account) }
|
||||
|
||||
context 'with an oauth token' do
|
||||
before do
|
||||
allow(controller).to receive(:doorkeeper_token) { token }
|
||||
subject do
|
||||
get "/api/v1/statuses/#{status.id}/reblogged_by", headers: headers, params: { limit: 2 }
|
||||
end
|
||||
|
||||
describe 'GET #index' do
|
||||
describe 'GET /api/v1/statuses/:status_id/reblogged_by' do
|
||||
let(:status) { Fabricate(:status, account: user.account) }
|
||||
|
||||
before do
|
||||
|
@ -25,27 +24,37 @@ RSpec.describe Api::V1::Statuses::RebloggedByAccountsController do
|
|||
end
|
||||
|
||||
it 'returns accounts who reblogged the status', :aggregate_failures do
|
||||
get :index, params: { status_id: status.id, limit: 2 }
|
||||
subject
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
expect(response.headers['Link'].links.size).to eq(2)
|
||||
expect(response)
|
||||
.to have_http_status(200)
|
||||
expect(response.headers['Link'].links.size)
|
||||
.to eq(2)
|
||||
|
||||
expect(body_as_json.size).to eq 2
|
||||
expect([body_as_json[0][:id], body_as_json[1][:id]]).to contain_exactly(alice.id.to_s, bob.id.to_s)
|
||||
expect(body_as_json.size)
|
||||
.to eq(2)
|
||||
expect(body_as_json)
|
||||
.to contain_exactly(
|
||||
include(id: alice.id.to_s),
|
||||
include(id: bob.id.to_s)
|
||||
)
|
||||
end
|
||||
|
||||
it 'does not return blocked users' do
|
||||
user.account.block!(bob)
|
||||
get :index, params: { status_id: status.id, limit: 2 }
|
||||
expect(body_as_json.size).to eq 1
|
||||
expect(body_as_json[0][:id]).to eq alice.id.to_s
|
||||
|
||||
subject
|
||||
|
||||
expect(body_as_json.size)
|
||||
.to eq 1
|
||||
expect(body_as_json.first[:id]).to eq(alice.id.to_s)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'without an oauth token' do
|
||||
before do
|
||||
allow(controller).to receive(:doorkeeper_token).and_return(nil)
|
||||
subject do
|
||||
get "/api/v1/statuses/#{status.id}/reblogged_by", params: { limit: 2 }
|
||||
end
|
||||
|
||||
context 'with a private status' do
|
||||
|
@ -57,7 +66,8 @@ RSpec.describe Api::V1::Statuses::RebloggedByAccountsController do
|
|||
end
|
||||
|
||||
it 'returns http unauthorized' do
|
||||
get :index, params: { status_id: status.id }
|
||||
subject
|
||||
|
||||
expect(response).to have_http_status(404)
|
||||
end
|
||||
end
|
||||
|
@ -72,7 +82,8 @@ RSpec.describe Api::V1::Statuses::RebloggedByAccountsController do
|
|||
end
|
||||
|
||||
it 'returns http success' do
|
||||
get :index, params: { status_id: status.id }
|
||||
subject
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
end
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue