diff --git a/Gemfile b/Gemfile
index 7f7da8c57fc106..2695a0be35e527 100644
--- a/Gemfile
+++ b/Gemfile
@@ -96,7 +96,7 @@ gem 'webpush', github: 'ClearlyClaire/webpush', ref: 'f14a4d52e201128b1b00245d11
gem 'webauthn', '~> 3.0'
gem 'json-ld'
-gem 'json-ld-preloaded', '~> 3.2'
+gem 'json-ld-preloaded', '~> 3.3'
gem 'rdf-normalize', '~> 0.5'
gem 'private_address_check', '~> 0.5'
diff --git a/Gemfile.lock b/Gemfile.lock
index 436f670a69f925..8c883ed830b357 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -380,9 +380,9 @@ GEM
multi_json (~> 1.15)
rack (>= 2.2, < 4)
rdf (~> 3.3)
- json-ld-preloaded (3.2.2)
- json-ld (~> 3.2)
- rdf (~> 3.2)
+ json-ld-preloaded (3.3.0)
+ json-ld (~> 3.3)
+ rdf (~> 3.3)
json-schema (4.0.0)
addressable (>= 2.8)
jsonapi-renderer (0.2.2)
@@ -864,7 +864,7 @@ DEPENDENCIES
i18n-tasks (~> 1.0)
idn-ruby
json-ld
- json-ld-preloaded (~> 3.2)
+ json-ld-preloaded (~> 3.3)
json-schema (~> 4.0)
kaminari (~> 1.2)
kt-paperclip (~> 7.2)
diff --git a/README.FLIPBOARD b/README.FLIPBOARD
new file mode 100644
index 00000000000000..fe76d1b1158170
--- /dev/null
+++ b/README.FLIPBOARD
@@ -0,0 +1,17 @@
+- added updater_post_install.sh script
+- added jenkins build script
+
+##############
+# To sync fork
+##############
+$ git fetch upstream
+$ git checkout main
+$ git merge upstream/main
+$ git push
+
+##############
+# To get tags from upstream
+##############
+$ git fetch --tags upstream
+$ git push --tags
+
diff --git a/app/controllers/api/v1/surf/accounts_controller.rb b/app/controllers/api/v1/surf/accounts_controller.rb
new file mode 100644
index 00000000000000..0bdb4294dfc516
--- /dev/null
+++ b/app/controllers/api/v1/surf/accounts_controller.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+class Api::V1::Surf::AccountsController < Api::BaseController
+ before_action -> { doorkeeper_authorize! :write, :'write:accounts' }, only: [:create]
+ before_action :check_enabled_registrations, only: [:create]
+
+ skip_before_action :require_authenticated_user!, only: :create
+
+ def create
+ token = SurfAppSignUpService.new.call(doorkeeper_token.application, request.remote_ip, account_params)
+ response = Doorkeeper::OAuth::TokenResponse.new(token)
+
+ headers.merge!(response.headers)
+ self.response_body = Oj.dump(response.body)
+ self.status = response.status
+ rescue ActiveRecord::RecordInvalid => e
+ render json: ValidationErrorFormatter.new(e, 'account.username': :username, 'invite_request.text': :reason).as_json, status: 422
+ end
+
+ private
+
+ def account_params
+ params.permit(:username, :email, :password, :agreement, :locale, :reason, :time_zone)
+ end
+
+ def check_enabled_registrations
+ forbidden if single_user_mode? || omniauth_only? || !allowed_registrations?
+ end
+
+ def allowed_registrations?
+ Setting.registrations_mode != 'none'
+ end
+
+ def omniauth_only?
+ ENV['OMNIAUTH_ONLY'] == 'true'
+ end
+end
diff --git a/app/controllers/api/v1/surf/emails_controller.rb b/app/controllers/api/v1/surf/emails_controller.rb
new file mode 100644
index 00000000000000..7f9631e431ff0a
--- /dev/null
+++ b/app/controllers/api/v1/surf/emails_controller.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+class Api::V1::Surf::EmailsController < Api::BaseController
+ # Notes:
+ # - Requires an access token.
+ # - @current_user is the access token resource owner
+ before_action :current_user
+
+ def confirmation
+ confirmation_params = { confirmation_token: @current_user.confirmation_token }
+ confirmation_url = "/auth/confirmation?#{confirmation_params.to_query}"
+ render json: {
+ base_url: request.base_url,
+ confirmation_url: confirmation_url,
+ username: @current_user.account.username,
+ email: @current_user.email,
+ }
+ end
+
+ def welcome
+ render json: {
+ base_url: request.base_url,
+ username: @current_user.account.username,
+ email: @current_user.email,
+ }
+ end
+end
diff --git a/app/controllers/api/v1/surf/users_controller.rb b/app/controllers/api/v1/surf/users_controller.rb
new file mode 100644
index 00000000000000..5ae94df9263b39
--- /dev/null
+++ b/app/controllers/api/v1/surf/users_controller.rb
@@ -0,0 +1,102 @@
+# frozen_string_literal: true
+
+class Api::V1::Surf::UsersController < Api::BaseController
+ before_action -> { doorkeeper_authorize! :write }, only: [:sign_in, :sign_out, :confirmation]
+ before_action -> { doorkeeper_authorize! :read }
+ before_action :require_user!, except: [:confirmation, :sign_in]
+
+ def whoami
+ # Requires: user access_token
+ user = @current_user.as_json
+ user[:confirmation_token] = @current_user.confirmation_token unless @current_user.confirmed?
+ render json: user
+ end
+
+ def sign_in
+ # Requires: app access_token
+ @current_user = User.find_by(email: params[:email])
+ raise(ActiveRecord::RecordNotFound) unless @current_user&.valid_password?(params[:password])
+
+ require_not_suspended!
+
+ # checks if they have an existing, valid access token
+ token = Doorkeeper::AccessToken.find_by(
+ resource_owner_id: @current_user.id,
+ application_id: doorkeeper_token.application,
+ revoked_at: nil
+ )
+ if token.nil?
+ token = Doorkeeper::AccessToken.create!(
+ application: doorkeeper_token.application,
+ resource_owner_id: @current_user.id,
+ scopes: doorkeeper_token.application.scopes,
+ expires_in: Doorkeeper.configuration.access_token_expires_in,
+ use_refresh_token: Doorkeeper.configuration.refresh_token_enabled?
+ )
+ end
+
+ update_user_sign_in
+ prepare_returning_user!
+
+ # prepare response
+ response = Doorkeeper::OAuth::TokenResponse.new(token)
+ headers.merge!(response.headers)
+ self.response_body = Oj.dump(response.body)
+ self.status = response.status
+ end
+
+ def sign_out
+ # Requires: user access_token
+ revoke_access!
+ render json: { message: 'All access tokens revoked.' }, status: 200
+ end
+
+ def confirmation
+ # Requires: app access_token
+ # Requires: confirmation_token
+ confirmation_token = params[:confirmation_token]
+ raise Mastodon::InvalidParameterError, 'Missing confirmation_token' unless confirmation_token
+
+ @current_user = User.find_first_by_auth_conditions(confirmation_token: confirmation_token)
+ raise(ActiveRecord::RecordNotFound) unless @current_user
+
+ # update confirmed_at, reset confirmation_token
+ @current_user.update!(
+ confirmed_at: Time.current,
+ confirmation_token: nil
+ )
+ prepare_new_user!
+ render json: { message: 'User confirmed.' }, status: 200
+ end
+
+ protected
+
+ def revoke_access!
+ # this method revokes all tokens for the current user
+ Doorkeeper::AccessToken.by_resource_owner(@current_user).in_batches do |batch|
+ batch.update_all(revoked_at: Time.now.utc) # rubocop:disable Rails/SkipsModelValidations
+ end
+ end
+
+ def require_user!
+ # Override require_user! because it prevents
+ # unconfirmed user access and might need to
+ # get the confirmation_token for sending the email
+ if current_user
+ update_user_sign_in
+ else
+ render json: { error: 'This method requires an authenticated user' }, status: 422
+ end
+ end
+
+ def prepare_new_user!
+ BootstrapTimelineWorker.perform_async(@current_user.account_id)
+ ActivityTracker.increment('activity:accounts:local')
+ ActivityTracker.record('activity:logins', @current_user.id)
+ TriggerWebhookWorker.perform_async('account.approved', 'Account', @current_user.account_id)
+ end
+
+ def prepare_returning_user!
+ ActivityTracker.record('activity:logins', @current_user.id)
+ end
+end
diff --git a/app/controllers/auth/registrations_controller.rb b/app/controllers/auth/registrations_controller.rb
index e70ae5b1b8b371..e7724e3e0afbbc 100644
--- a/app/controllers/auth/registrations_controller.rb
+++ b/app/controllers/auth/registrations_controller.rb
@@ -55,7 +55,7 @@ def build_resource(hash = nil)
def configure_sign_up_params
devise_parameter_sanitizer.permit(:sign_up) do |user_params|
- user_params.permit({ account_attributes: [:username, :display_name], invite_request_attributes: [:text] }, :email, :password, :password_confirmation, :invite_code, :agreement, :website, :confirm_password)
+ user_params.permit({ account_attributes: [:username, :display_name], invite_request_attributes: [:text, :flipboard_username] }, :email, :password, :password_confirmation, :invite_code, :agreement, :website, :confirm_password)
end
end
diff --git a/app/helpers/branding_helper.rb b/app/helpers/branding_helper.rb
index 2b9c233c23bcfa..860934a3f80a65 100644
--- a/app/helpers/branding_helper.rb
+++ b/app/helpers/branding_helper.rb
@@ -11,7 +11,7 @@ def logo_as_symbol(version = :icon)
end
def _logo_as_symbol_wordmark
- content_tag(:svg, tag.use(href: '#logo-symbol-wordmark'), viewBox: '0 0 261 66', class: 'logo logo--wordmark')
+ content_tag(:svg, tag.use(href: '#logo-symbol-wordmark'), viewBox: '0 0 500 500', class: 'logo logo--wordmark')
end
def _logo_as_symbol_icon
diff --git a/app/javascript/images/app-icon.svg b/app/javascript/images/app-icon.svg
index 1035bd076e873b..09e1cae9ec00ab 100644
--- a/app/javascript/images/app-icon.svg
+++ b/app/javascript/images/app-icon.svg
@@ -1,28 +1 @@
-
+
\ No newline at end of file
diff --git a/app/javascript/images/logo-symbol-icon.svg b/app/javascript/images/logo-symbol-icon.svg
index c4c14f098afa02..09e1cae9ec00ab 100644
--- a/app/javascript/images/logo-symbol-icon.svg
+++ b/app/javascript/images/logo-symbol-icon.svg
@@ -1,2 +1 @@
-
-
+
\ No newline at end of file
diff --git a/app/javascript/images/logo-symbol-wordmark.svg b/app/javascript/images/logo-symbol-wordmark.svg
index ee0b636d936fa3..98833d696623b7 100644
--- a/app/javascript/images/logo-symbol-wordmark.svg
+++ b/app/javascript/images/logo-symbol-wordmark.svg
@@ -1,11 +1 @@
-
+
diff --git a/app/javascript/images/logo.svg b/app/javascript/images/logo.svg
index 11d0c30c56271b..09e1cae9ec00ab 100644
--- a/app/javascript/images/logo.svg
+++ b/app/javascript/images/logo.svg
@@ -1,10 +1 @@
-
+
\ No newline at end of file
diff --git a/app/javascript/images/mailer/logo.png b/app/javascript/images/mailer/logo.png
index 784be9539f3474..89b030a691a337 100644
Binary files a/app/javascript/images/mailer/logo.png and b/app/javascript/images/mailer/logo.png differ
diff --git a/app/javascript/images/mailer/wordmark.png b/app/javascript/images/mailer/wordmark.png
index 6772b3318dc35c..2a0ca522f2d596 100644
Binary files a/app/javascript/images/mailer/wordmark.png and b/app/javascript/images/mailer/wordmark.png differ
diff --git a/app/javascript/images/preview.png b/app/javascript/images/preview.png
index 3d3a17b23c5591..9e247425f264f4 100644
Binary files a/app/javascript/images/preview.png and b/app/javascript/images/preview.png differ
diff --git a/app/javascript/mastodon/features/compose/components/compose_form.jsx b/app/javascript/mastodon/features/compose/components/compose_form.jsx
index 9222b2dc87703b..962310a284a6bc 100644
--- a/app/javascript/mastodon/features/compose/components/compose_form.jsx
+++ b/app/javascript/mastodon/features/compose/components/compose_form.jsx
@@ -100,7 +100,7 @@ class ComposeForm extends ImmutablePureComponent {
const fulltext = this.getFulltextForCharacterCounting();
const isOnlyWhitespace = fulltext.length !== 0 && fulltext.trim().length === 0;
- return !(isSubmitting || isUploading || isChangingUpload || length(fulltext) > 500 || (isOnlyWhitespace && !anyMedia));
+ return !(isSubmitting || isUploading || isChangingUpload || length(fulltext) > 5000 || (isOnlyWhitespace && !anyMedia));
};
handleSubmit = (e) => {
@@ -297,7 +297,7 @@ class ComposeForm extends ImmutablePureComponent {
-
+
diff --git a/app/javascript/mastodon/features/compose/components/poll_form.jsx b/app/javascript/mastodon/features/compose/components/poll_form.jsx
index 1a4d30abe71393..394faeae2e1b01 100644
--- a/app/javascript/mastodon/features/compose/components/poll_form.jsx
+++ b/app/javascript/mastodon/features/compose/components/poll_form.jsx
@@ -164,7 +164,7 @@ class PollForm extends ImmutablePureComponent {
-
+
{/* eslint-disable-next-line jsx-a11y/no-onchange */}