Merge remote-tracking branch 'origin/master' into gs-master
Conflicts: db/schema.rb
This commit is contained in:
		@@ -8,7 +8,9 @@ class Settings::ProfilesController < Settings::BaseController
 | 
			
		||||
  obfuscate_filename [:account, :avatar]
 | 
			
		||||
  obfuscate_filename [:account, :header]
 | 
			
		||||
 | 
			
		||||
  def show; end
 | 
			
		||||
  def show
 | 
			
		||||
    @account.build_fields
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def update
 | 
			
		||||
    if UpdateAccountService.new.call(@account, account_params)
 | 
			
		||||
@@ -22,7 +24,7 @@ class Settings::ProfilesController < Settings::BaseController
 | 
			
		||||
  private
 | 
			
		||||
 | 
			
		||||
  def account_params
 | 
			
		||||
    params.require(:account).permit(:display_name, :note, :avatar, :header, :locked)
 | 
			
		||||
    params.require(:account).permit(:display_name, :note, :avatar, :header, :locked, fields_attributes: [:name, :value])
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def set_account
 | 
			
		||||
 
 | 
			
		||||
@@ -10,6 +10,14 @@ export function normalizeAccount(account) {
 | 
			
		||||
  account.display_name_html = emojify(escapeTextContentForBrowser(displayName));
 | 
			
		||||
  account.note_emojified = emojify(account.note);
 | 
			
		||||
 | 
			
		||||
  if (account.fields) {
 | 
			
		||||
    account.fields = account.fields.map(pair => ({
 | 
			
		||||
      ...pair,
 | 
			
		||||
      name_emojified: emojify(escapeTextContentForBrowser(pair.name)),
 | 
			
		||||
      value_emojified: emojify(pair.value),
 | 
			
		||||
    }));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (account.moved) {
 | 
			
		||||
    account.moved = account.moved.id;
 | 
			
		||||
  }
 | 
			
		||||
 
 | 
			
		||||
@@ -130,6 +130,7 @@ export default class Header extends ImmutablePureComponent {
 | 
			
		||||
 | 
			
		||||
    const content         = { __html: account.get('note_emojified') };
 | 
			
		||||
    const displayNameHtml = { __html: account.get('display_name_html') };
 | 
			
		||||
    const fields          = account.get('fields');
 | 
			
		||||
 | 
			
		||||
    return (
 | 
			
		||||
      <div className={classNames('account__header', { inactive: !!account.get('moved') })} style={{ backgroundImage: `url(${account.get('header')})` }}>
 | 
			
		||||
@@ -140,6 +141,19 @@ export default class Header extends ImmutablePureComponent {
 | 
			
		||||
          <span className='account__header__username'>@{account.get('acct')} {lockedIcon}</span>
 | 
			
		||||
          <div className='account__header__content' dangerouslySetInnerHTML={content} />
 | 
			
		||||
 | 
			
		||||
          {fields.size > 0 && (
 | 
			
		||||
            <table className='account__header__fields'>
 | 
			
		||||
              <tbody>
 | 
			
		||||
                {fields.map((pair, i) => (
 | 
			
		||||
                  <tr key={i}>
 | 
			
		||||
                    <th dangerouslySetInnerHTML={{ __html: pair.get('name_emojified') }} />
 | 
			
		||||
                    <td dangerouslySetInnerHTML={{ __html: pair.get('value_emojified') }} />
 | 
			
		||||
                  </tr>
 | 
			
		||||
                ))}
 | 
			
		||||
              </tbody>
 | 
			
		||||
            </table>
 | 
			
		||||
          )}
 | 
			
		||||
 | 
			
		||||
          {info}
 | 
			
		||||
          {mutingInfo}
 | 
			
		||||
          {actionBtn}
 | 
			
		||||
 
 | 
			
		||||
@@ -563,3 +563,57 @@
 | 
			
		||||
    border-color: rgba(lighten($error-red, 12%), 0.5);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.account__header__fields {
 | 
			
		||||
  border-collapse: collapse;
 | 
			
		||||
  padding: 0;
 | 
			
		||||
  margin: 15px -15px -15px;
 | 
			
		||||
  border: 0 none;
 | 
			
		||||
  border-top: 1px solid lighten($ui-base-color, 4%);
 | 
			
		||||
  border-bottom: 1px solid lighten($ui-base-color, 4%);
 | 
			
		||||
 | 
			
		||||
  th,
 | 
			
		||||
  td {
 | 
			
		||||
    padding: 15px;
 | 
			
		||||
    padding-left: 15px;
 | 
			
		||||
    border: 0 none;
 | 
			
		||||
    border-bottom: 1px solid lighten($ui-base-color, 4%);
 | 
			
		||||
    vertical-align: middle;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  th {
 | 
			
		||||
    padding-left: 15px;
 | 
			
		||||
    font-weight: 500;
 | 
			
		||||
    text-align: center;
 | 
			
		||||
    width: 94px;
 | 
			
		||||
    color: $ui-secondary-color;
 | 
			
		||||
    background: rgba(darken($ui-base-color, 8%), 0.5);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  td {
 | 
			
		||||
    color: $ui-primary-color;
 | 
			
		||||
    text-align: center;
 | 
			
		||||
    width: 100%;
 | 
			
		||||
    padding-left: 0;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  a {
 | 
			
		||||
    color: $ui-highlight-color;
 | 
			
		||||
    text-decoration: none;
 | 
			
		||||
 | 
			
		||||
    &:hover,
 | 
			
		||||
    &:focus,
 | 
			
		||||
    &:active {
 | 
			
		||||
      text-decoration: underline;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  tr {
 | 
			
		||||
    &:last-child {
 | 
			
		||||
      th,
 | 
			
		||||
      td {
 | 
			
		||||
        border-bottom: 0;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -5176,3 +5176,40 @@ noscript {
 | 
			
		||||
    background: lighten($ui-highlight-color, 7%);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.account__header .account__header__fields {
 | 
			
		||||
  font-size: 14px;
 | 
			
		||||
  line-height: 20px;
 | 
			
		||||
  overflow: hidden;
 | 
			
		||||
  border-collapse: collapse;
 | 
			
		||||
  margin: 20px -10px -20px;
 | 
			
		||||
  border-bottom: 0;
 | 
			
		||||
 | 
			
		||||
  tr {
 | 
			
		||||
    border-top: 1px solid lighten($ui-base-color, 8%);
 | 
			
		||||
    text-align: center;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  th,
 | 
			
		||||
  td {
 | 
			
		||||
    padding: 14px 20px;
 | 
			
		||||
    vertical-align: middle;
 | 
			
		||||
    max-height: 40px;
 | 
			
		||||
    overflow: hidden;
 | 
			
		||||
    white-space: nowrap;
 | 
			
		||||
    text-overflow: ellipsis;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  th {
 | 
			
		||||
    color: $ui-primary-color;
 | 
			
		||||
    background: darken($ui-base-color, 4%);
 | 
			
		||||
    max-width: 120px;
 | 
			
		||||
    font-weight: 500;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  td {
 | 
			
		||||
    flex: auto;
 | 
			
		||||
    color: $primary-text-color;
 | 
			
		||||
    background: $ui-base-color;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -15,6 +15,18 @@ code {
 | 
			
		||||
    overflow: hidden;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .row {
 | 
			
		||||
    display: flex;
 | 
			
		||||
    margin: 0 -5px;
 | 
			
		||||
 | 
			
		||||
    .input {
 | 
			
		||||
      box-sizing: border-box;
 | 
			
		||||
      flex: 1 1 auto;
 | 
			
		||||
      width: 50%;
 | 
			
		||||
      padding: 0 5px;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  span.hint {
 | 
			
		||||
    display: block;
 | 
			
		||||
    color: $ui-primary-color;
 | 
			
		||||
 
 | 
			
		||||
@@ -19,6 +19,9 @@ class ActivityPub::Adapter < ActiveModelSerializers::Adapter::Base
 | 
			
		||||
        'Emoji'                     => 'toot:Emoji',
 | 
			
		||||
        'focalPoint'                => { '@container' => '@list', '@id' => 'toot:focalPoint' },
 | 
			
		||||
        'featured'                  => 'toot:featured',
 | 
			
		||||
        'schema'                    => 'http://schema.org#',
 | 
			
		||||
        'PropertyValue'             => 'schema:PropertyValue',
 | 
			
		||||
        'value'                     => 'schema:value',
 | 
			
		||||
      },
 | 
			
		||||
    ],
 | 
			
		||||
  }.freeze
 | 
			
		||||
 
 | 
			
		||||
@@ -71,6 +71,11 @@ class Formatter
 | 
			
		||||
    html.html_safe # rubocop:disable Rails/OutputSafety
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def format_field(account, str)
 | 
			
		||||
    return reformat(str).html_safe unless account.local? # rubocop:disable Rails/OutputSafety
 | 
			
		||||
    encode_and_link_urls(str, me: true).html_safe # rubocop:disable Rails/OutputSafety
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def linkify(text)
 | 
			
		||||
    html = encode_and_link_urls(text)
 | 
			
		||||
    html = simple_format(html, {}, sanitize: false)
 | 
			
		||||
@@ -85,12 +90,17 @@ class Formatter
 | 
			
		||||
    HTMLEntities.new.encode(html)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def encode_and_link_urls(html, accounts = nil)
 | 
			
		||||
  def encode_and_link_urls(html, accounts = nil, options = {})
 | 
			
		||||
    entities = Extractor.extract_entities_with_indices(html, extract_url_without_protocol: false)
 | 
			
		||||
 | 
			
		||||
    if accounts.is_a?(Hash)
 | 
			
		||||
      options  = accounts
 | 
			
		||||
      accounts = nil
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    rewrite(html.dup, entities) do |entity|
 | 
			
		||||
      if entity[:url]
 | 
			
		||||
        link_to_url(entity)
 | 
			
		||||
        link_to_url(entity, options)
 | 
			
		||||
      elsif entity[:hashtag]
 | 
			
		||||
        link_to_hashtag(entity)
 | 
			
		||||
      elsif entity[:screen_name]
 | 
			
		||||
@@ -177,10 +187,12 @@ class Formatter
 | 
			
		||||
    result.flatten.join
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def link_to_url(entity)
 | 
			
		||||
  def link_to_url(entity, options = {})
 | 
			
		||||
    url        = Addressable::URI.parse(entity[:url])
 | 
			
		||||
    html_attrs = { target: '_blank', rel: 'nofollow noopener' }
 | 
			
		||||
 | 
			
		||||
    html_attrs[:rel] = "me #{html_attrs[:rel]}" if options[:me]
 | 
			
		||||
 | 
			
		||||
    Twitter::Autolink.send(:link_to_text, entity, link_html(entity[:url]), url, html_attrs)
 | 
			
		||||
  rescue Addressable::URI::InvalidURIError, IDN::Idna::IdnaError
 | 
			
		||||
    encode(entity[:url])
 | 
			
		||||
 
 | 
			
		||||
@@ -44,6 +44,7 @@
 | 
			
		||||
#  memorial                :boolean          default(FALSE), not null
 | 
			
		||||
#  moved_to_account_id     :integer
 | 
			
		||||
#  featured_collection_url :string
 | 
			
		||||
#  fields                  :jsonb
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
class Account < ApplicationRecord
 | 
			
		||||
@@ -192,6 +193,30 @@ class Account < ApplicationRecord
 | 
			
		||||
    @keypair ||= OpenSSL::PKey::RSA.new(private_key || public_key)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def fields
 | 
			
		||||
    (self[:fields] || []).map { |f| Field.new(self, f) }
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def fields_attributes=(attributes)
 | 
			
		||||
    fields = []
 | 
			
		||||
 | 
			
		||||
    attributes.each_value do |attr|
 | 
			
		||||
      next if attr[:name].blank?
 | 
			
		||||
      fields << attr
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    self[:fields] = fields
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def build_fields
 | 
			
		||||
    return if fields.size >= 4
 | 
			
		||||
 | 
			
		||||
    raw_fields = self[:fields] || []
 | 
			
		||||
    add_fields = 4 - raw_fields.size
 | 
			
		||||
    add_fields.times { raw_fields << { name: '', value: '' } }
 | 
			
		||||
    self.fields = raw_fields
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def magic_key
 | 
			
		||||
    modulus, exponent = [keypair.public_key.n, keypair.public_key.e].map do |component|
 | 
			
		||||
      result = []
 | 
			
		||||
@@ -241,6 +266,17 @@ class Account < ApplicationRecord
 | 
			
		||||
    shared_inbox_url.presence || inbox_url
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  class Field < ActiveModelSerializers::Model
 | 
			
		||||
    attributes :name, :value, :account, :errors
 | 
			
		||||
 | 
			
		||||
    def initialize(account, attr)
 | 
			
		||||
      @account = account
 | 
			
		||||
      @name    = attr['name']
 | 
			
		||||
      @value   = attr['value']
 | 
			
		||||
      @errors  = {}
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  class << self
 | 
			
		||||
    def readonly_attributes
 | 
			
		||||
      super - %w(statuses_count following_count followers_count)
 | 
			
		||||
 
 | 
			
		||||
@@ -11,6 +11,7 @@ class ActivityPub::ActorSerializer < ActiveModel::Serializer
 | 
			
		||||
  has_one :public_key, serializer: ActivityPub::PublicKeySerializer
 | 
			
		||||
 | 
			
		||||
  has_many :virtual_tags, key: :tag
 | 
			
		||||
  has_many :virtual_attachments, key: :attachment
 | 
			
		||||
 | 
			
		||||
  attribute :moved_to, if: :moved?
 | 
			
		||||
 | 
			
		||||
@@ -107,10 +108,26 @@ class ActivityPub::ActorSerializer < ActiveModel::Serializer
 | 
			
		||||
    object.emojis
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def virtual_attachments
 | 
			
		||||
    object.fields
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def moved_to
 | 
			
		||||
    ActivityPub::TagManager.instance.uri_for(object.moved_to_account)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  class CustomEmojiSerializer < ActivityPub::EmojiSerializer
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  class Account::FieldSerializer < ActiveModel::Serializer
 | 
			
		||||
    attributes :type, :name, :value
 | 
			
		||||
 | 
			
		||||
    def type
 | 
			
		||||
      'PropertyValue'
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def value
 | 
			
		||||
      Formatter.instance.format_field(object.account, object.value)
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 
 | 
			
		||||
@@ -9,6 +9,16 @@ class REST::AccountSerializer < ActiveModel::Serializer
 | 
			
		||||
 | 
			
		||||
  has_one :moved_to_account, key: :moved, serializer: REST::AccountSerializer, if: :moved_and_not_nested?
 | 
			
		||||
 | 
			
		||||
  class FieldSerializer < ActiveModel::Serializer
 | 
			
		||||
    attributes :name, :value
 | 
			
		||||
 | 
			
		||||
    def value
 | 
			
		||||
      Formatter.instance.format_field(object.account, object.value)
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  has_many :fields
 | 
			
		||||
 | 
			
		||||
  def id
 | 
			
		||||
    object.id.to_s
 | 
			
		||||
  end
 | 
			
		||||
 
 | 
			
		||||
@@ -70,6 +70,7 @@ class ActivityPub::ProcessAccountService < BaseService
 | 
			
		||||
    @account.display_name            = @json['name'] || ''
 | 
			
		||||
    @account.note                    = @json['summary'] || ''
 | 
			
		||||
    @account.locked                  = @json['manuallyApprovesFollowers'] || false
 | 
			
		||||
    @account.fields                  = property_values || {}
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def set_fetchable_attributes!
 | 
			
		||||
@@ -126,6 +127,11 @@ class ActivityPub::ProcessAccountService < BaseService
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def property_values
 | 
			
		||||
    return unless @json['attachment'].is_a?(Array)
 | 
			
		||||
    @json['attachment'].select { |attachment| attachment['type'] == 'PropertyValue' }.map { |attachment| attachment.slice('name', 'value') }
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def mismatching_origin?(url)
 | 
			
		||||
    needle   = Addressable::URI.parse(url).host
 | 
			
		||||
    haystack = Addressable::URI.parse(@uri).host
 | 
			
		||||
 
 | 
			
		||||
@@ -28,6 +28,14 @@
 | 
			
		||||
              %th.emojify>!=i[0]
 | 
			
		||||
              %td.emojify>!=i[1]
 | 
			
		||||
 | 
			
		||||
      - unless account.fields.empty?
 | 
			
		||||
        %table.account__header__fields
 | 
			
		||||
          %tbody
 | 
			
		||||
            - account.fields.each do |field|
 | 
			
		||||
              %tr
 | 
			
		||||
                %th.emojify= field.name
 | 
			
		||||
                %td.emojify= Formatter.instance.format_field(account, field.value)
 | 
			
		||||
 | 
			
		||||
    .details-counters
 | 
			
		||||
      .counter{ class: active_nav_class(short_account_url(account)) }
 | 
			
		||||
        = link_to short_account_url(account), class: 'u-url u-uid' do
 | 
			
		||||
 
 | 
			
		||||
@@ -19,6 +19,16 @@
 | 
			
		||||
  .fields-group
 | 
			
		||||
    = f.input :locked, as: :boolean, wrapper: :with_label, hint: t('simple_form.hints.defaults.locked')
 | 
			
		||||
 | 
			
		||||
  .fields-group
 | 
			
		||||
    .input.with_block_label
 | 
			
		||||
      %label= t('simple_form.labels.defaults.fields')
 | 
			
		||||
      %span.hint= t('simple_form.hints.defaults.fields')
 | 
			
		||||
 | 
			
		||||
      = f.simple_fields_for :fields do |fields_f|
 | 
			
		||||
        .row
 | 
			
		||||
          = fields_f.input :name, placeholder: t('simple_form.labels.account.fields.name')
 | 
			
		||||
          = fields_f.input :value, placeholder: t('simple_form.labels.account.fields.value')
 | 
			
		||||
 | 
			
		||||
  .actions
 | 
			
		||||
    = f.button :button, t('generic.save_changes'), type: :submit
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -8,6 +8,7 @@ en:
 | 
			
		||||
        display_name:
 | 
			
		||||
          one: <span class="name-counter">1</span> character left
 | 
			
		||||
          other: <span class="name-counter">%{count}</span> characters left
 | 
			
		||||
        fields: You can have up to 4 items displayed as a table on your profile
 | 
			
		||||
        header: PNG, GIF or JPG. At most 2MB. Will be downscaled to 700x335px
 | 
			
		||||
        locked: Requires you to manually approve followers
 | 
			
		||||
        note:
 | 
			
		||||
@@ -22,6 +23,10 @@ en:
 | 
			
		||||
      user:
 | 
			
		||||
        filtered_languages: Checked languages will be filtered from public timelines for you
 | 
			
		||||
    labels:
 | 
			
		||||
      account:
 | 
			
		||||
        fields:
 | 
			
		||||
          name: Label
 | 
			
		||||
          value: Content
 | 
			
		||||
      defaults:
 | 
			
		||||
        avatar: Avatar
 | 
			
		||||
        confirm_new_password: Confirm new password
 | 
			
		||||
@@ -31,6 +36,7 @@ en:
 | 
			
		||||
        display_name: Display name
 | 
			
		||||
        email: E-mail address
 | 
			
		||||
        expires_in: Expire after
 | 
			
		||||
        fields: Profile metadata
 | 
			
		||||
        filtered_languages: Filtered languages
 | 
			
		||||
        header: Header
 | 
			
		||||
        locale: Language
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										5
									
								
								db/migrate/20180410204633_add_fields_to_accounts.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								db/migrate/20180410204633_add_fields_to_accounts.rb
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
			
		||||
class AddFieldsToAccounts < ActiveRecord::Migration[5.1]
 | 
			
		||||
  def change
 | 
			
		||||
    add_column :accounts, :fields, :jsonb
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
@@ -10,7 +10,7 @@
 | 
			
		||||
#
 | 
			
		||||
# It's strongly recommended that you check this file into your version control system.
 | 
			
		||||
 | 
			
		||||
ActiveRecord::Schema.define(version: 20180410220657) do
 | 
			
		||||
ActiveRecord::Schema.define(version: 2018_04_10_204633) do
 | 
			
		||||
 | 
			
		||||
  # These are extensions that must be enabled in order to support this database
 | 
			
		||||
  enable_extension "pg_stat_statements"
 | 
			
		||||
@@ -75,6 +75,7 @@ ActiveRecord::Schema.define(version: 20180410220657) do
 | 
			
		||||
    t.boolean "memorial", default: false, null: false
 | 
			
		||||
    t.bigint "moved_to_account_id"
 | 
			
		||||
    t.string "featured_collection_url"
 | 
			
		||||
    t.jsonb "fields"
 | 
			
		||||
    t.index "(((setweight(to_tsvector('simple'::regconfig, (display_name)::text), 'A'::\"char\") || setweight(to_tsvector('simple'::regconfig, (username)::text), 'B'::\"char\")) || setweight(to_tsvector('simple'::regconfig, (COALESCE(domain, ''::character varying))::text), 'C'::\"char\")))", name: "search_index", using: :gin
 | 
			
		||||
    t.index "lower((username)::text), lower((domain)::text)", name: "index_accounts_on_username_and_domain_lower"
 | 
			
		||||
    t.index ["uri"], name: "index_accounts_on_uri"
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,31 @@
 | 
			
		||||
require 'rails_helper'
 | 
			
		||||
 | 
			
		||||
RSpec.describe ActivityPub::ProcessAccountService do
 | 
			
		||||
  pending
 | 
			
		||||
  subject { described_class.new }
 | 
			
		||||
 | 
			
		||||
  context 'property values' do
 | 
			
		||||
    let(:payload) do
 | 
			
		||||
      {
 | 
			
		||||
        id: 'https://foo',
 | 
			
		||||
        type: 'Actor',
 | 
			
		||||
        inbox: 'https://foo/inbox',
 | 
			
		||||
        attachment: [
 | 
			
		||||
          { type: 'PropertyValue', name: 'Pronouns', value: 'They/them' },
 | 
			
		||||
          { type: 'PropertyValue', name: 'Occupation', value: 'Unit test' },
 | 
			
		||||
        ],
 | 
			
		||||
      }.with_indifferent_access
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it 'parses out of attachment' do
 | 
			
		||||
      account = subject.call('alice', 'example.com', payload)
 | 
			
		||||
      expect(account.fields).to be_a Array
 | 
			
		||||
      expect(account.fields.size).to eq 2
 | 
			
		||||
      expect(account.fields[0]).to be_a Account::Field
 | 
			
		||||
      expect(account.fields[0].name).to eq 'Pronouns'
 | 
			
		||||
      expect(account.fields[0].value).to eq 'They/them'
 | 
			
		||||
      expect(account.fields[1]).to be_a Account::Field
 | 
			
		||||
      expect(account.fields[1].name).to eq 'Occupation'
 | 
			
		||||
      expect(account.fields[1].value).to eq 'Unit test'
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user