about summary refs log tree commit diff
path: root/config
diff options
context:
space:
mode:
Diffstat (limited to 'config')
-rw-r--r--config/brakeman.ignore228
-rw-r--r--config/initializers/doorkeeper.rb3
-rw-r--r--config/initializers/inflections.rb1
-rw-r--r--config/locales/en.yml22
-rw-r--r--config/locales/simple_form.en.yml1
-rw-r--r--config/routes.rb18
-rw-r--r--config/webpack/shared.js10
7 files changed, 161 insertions, 122 deletions
diff --git a/config/brakeman.ignore b/config/brakeman.ignore
index 7e3828f7e..baa993c78 100644
--- a/config/brakeman.ignore
+++ b/config/brakeman.ignore
@@ -1,33 +1,13 @@
 {
   "ignored_warnings": [
     {
-      "warning_type": "Mass Assignment",
-      "warning_code": 105,
-      "fingerprint": "0117d2be5947ea4e4fbed9c15f23c6615b12c6892973411820c83d079808819d",
-      "check_name": "PermitAttributes",
-      "message": "Potentially dangerous key allowed for mass assignment",
-      "file": "app/controllers/api/v1/search_controller.rb",
-      "line": 30,
-      "link": "https://brakemanscanner.org/docs/warning_types/mass_assignment/",
-      "code": "params.permit(:type, :offset, :min_id, :max_id, :account_id)",
-      "render_path": null,
-      "location": {
-        "type": "method",
-        "class": "Api::V1::SearchController",
-        "method": "search_params"
-      },
-      "user_input": ":account_id",
-      "confidence": "High",
-      "note": ""
-    },
-    {
       "warning_type": "SQL Injection",
       "warning_code": 0,
       "fingerprint": "04dbbc249b989db2e0119bbb0f59c9818e12889d2b97c529cdc0b1526002ba4b",
       "check_name": "SQL",
       "message": "Possible SQL injection",
       "file": "app/models/report.rb",
-      "line": 90,
+      "line": 112,
       "link": "https://brakemanscanner.org/docs/warning_types/sql_injection/",
       "code": "Admin::ActionLog.from(\"(#{[Admin::ActionLog.where(:target_type => \"Report\", :target_id => id, :created_at => ((created_at..updated_at))).unscope(:order), Admin::ActionLog.where(:target_type => \"Account\", :target_id => target_account_id, :created_at => ((created_at..updated_at))).unscope(:order), Admin::ActionLog.where(:target_type => \"Status\", :target_id => status_ids, :created_at => ((created_at..updated_at))).unscope(:order)].map do\n \"(#{query.to_sql})\"\n end.join(\" UNION ALL \")}) AS admin_action_logs\")",
       "render_path": null,
@@ -47,7 +27,7 @@
       "check_name": "SQL",
       "message": "Possible SQL injection",
       "file": "app/models/status.rb",
-      "line": 87,
+      "line": 100,
       "link": "https://brakemanscanner.org/docs/warning_types/sql_injection/",
       "code": "result.joins(\"INNER JOIN statuses_tags t#{id} ON t#{id}.status_id = statuses.id AND t#{id}.tag_id = #{id}\")",
       "render_path": null,
@@ -61,39 +41,62 @@
       "note": ""
     },
     {
-      "warning_type": "Mass Assignment",
-      "warning_code": 105,
-      "fingerprint": "28d81cc22580ef76e912b077b245f353499aa27b3826476667224c00227af2a9",
-      "check_name": "PermitAttributes",
-      "message": "Potentially dangerous key allowed for mass assignment",
-      "file": "app/controllers/admin/reports_controller.rb",
-      "line": 56,
-      "link": "https://brakemanscanner.org/docs/warning_types/mass_assignment/",
-      "code": "params.permit(:account_id, :resolved, :target_account_id)",
-      "render_path": null,
+      "warning_type": "Dynamic Render Path",
+      "warning_code": 15,
+      "fingerprint": "20a660939f2bbf8c665e69f2844031c0564524689a9570a0091ed94846212020",
+      "check_name": "Render",
+      "message": "Render path contains parameter value",
+      "file": "app/views/admin/action_logs/index.html.haml",
+      "line": 26,
+      "link": "https://brakemanscanner.org/docs/warning_types/dynamic_render_path/",
+      "code": "render(action => Admin::ActionLogFilter.new(filter_params).results.page(params[:page]), {})",
+      "render_path": [
+        {
+          "type": "controller",
+          "class": "Admin::ActionLogsController",
+          "method": "index",
+          "line": 8,
+          "file": "app/controllers/admin/action_logs_controller.rb",
+          "rendered": {
+            "name": "admin/action_logs/index",
+            "file": "app/views/admin/action_logs/index.html.haml"
+          }
+        }
+      ],
       "location": {
-        "type": "method",
-        "class": "Admin::ReportsController",
-        "method": "filter_params"
+        "type": "template",
+        "template": "admin/action_logs/index"
       },
-      "user_input": ":account_id",
-      "confidence": "High",
+      "user_input": "params[:page]",
+      "confidence": "Weak",
       "note": ""
     },
     {
       "warning_type": "Dynamic Render Path",
       "warning_code": 15,
-      "fingerprint": "4b6a895e2805578d03ceedbe1d469cc75a0c759eba093722523edb4b8683c873",
+      "fingerprint": "371fe16dc4c9d6ab08a20437d65be4825776107a67c38f6d4780a9c703cd44a5",
       "check_name": "Render",
       "message": "Render path contains parameter value",
-      "file": "app/views/admin/action_logs/index.html.haml",
-      "line": 4,
+      "file": "app/views/admin/email_domain_blocks/index.html.haml",
+      "line": 17,
       "link": "https://brakemanscanner.org/docs/warning_types/dynamic_render_path/",
-      "code": "render(action => Admin::ActionLog.page(params[:page]), {})",
-      "render_path": [{"type":"controller","class":"Admin::ActionLogsController","method":"index","line":7,"file":"app/controllers/admin/action_logs_controller.rb","rendered":{"name":"admin/action_logs/index","file":"/home/eugr/Projects/mastodon/app/views/admin/action_logs/index.html.haml"}}],
+      "code": "render(action => EmailDomainBlock.where(:parent_id => nil).includes(:children).order(:id => :desc).page(params[:page]), {})",
+      "render_path": [
+        {
+          "type": "controller",
+          "class": "Admin::EmailDomainBlocksController",
+          "method": "index",
+          "line": 10,
+          "file": "app/controllers/admin/email_domain_blocks_controller.rb",
+          "rendered": {
+            "name": "admin/email_domain_blocks/index",
+            "file": "app/views/admin/email_domain_blocks/index.html.haml"
+          }
+        }
+      ],
       "location": {
         "type": "template",
-        "template": "admin/action_logs/index"
+        "template": "admin/email_domain_blocks/index"
       },
       "user_input": "params[:page]",
       "confidence": "Weak",
@@ -106,7 +109,7 @@
       "check_name": "Redirect",
       "message": "Possible unprotected redirect",
       "file": "app/controllers/remote_interaction_controller.rb",
-      "line": 21,
+      "line": 24,
       "link": "https://brakemanscanner.org/docs/warning_types/redirect/",
       "code": "redirect_to(RemoteFollow.new(resource_params).interact_address_for(Status.find(params[:id])))",
       "render_path": null,
@@ -120,32 +123,13 @@
       "note": ""
     },
     {
-      "warning_type": "Dynamic Render Path",
-      "warning_code": 15,
-      "fingerprint": "67afc0d5f7775fa5bd91d1912e1b5505aeedef61876347546fa20f92fd6915e6",
-      "check_name": "Render",
-      "message": "Render path contains parameter value",
-      "file": "app/views/stream_entries/embed.html.haml",
-      "line": 3,
-      "link": "https://brakemanscanner.org/docs/warning_types/dynamic_render_path/",
-      "code": "render(action => \"stream_entries/#{Account.find_local!(params[:account_username]).statuses.find(params[:id]).stream_entry.activity_type.downcase}\", { Account.find_local!(params[:account_username]).statuses.find(params[:id]).stream_entry.activity_type.downcase.to_sym => Account.find_local!(params[:account_username]).statuses.find(params[:id]).stream_entry.activity, :centered => true, :autoplay => ActiveModel::Type::Boolean.new.cast(params[:autoplay]) })",
-      "render_path": [{"type":"controller","class":"StatusesController","method":"embed","line":63,"file":"app/controllers/statuses_controller.rb","rendered":{"name":"stream_entries/embed","file":"/home/eugr/Projects/mastodon/app/views/stream_entries/embed.html.haml"}}],
-      "location": {
-        "type": "template",
-        "template": "stream_entries/embed"
-      },
-      "user_input": "params[:id]",
-      "confidence": "Weak",
-      "note": ""
-    },
-    {
       "warning_type": "SQL Injection",
       "warning_code": 0,
       "fingerprint": "6f075c1484908e3ec9bed21ab7cf3c7866be8da3881485d1c82e13093aefcbd7",
       "check_name": "SQL",
       "message": "Possible SQL injection",
       "file": "app/models/status.rb",
-      "line": 92,
+      "line": 105,
       "link": "https://brakemanscanner.org/docs/warning_types/sql_injection/",
       "code": "result.joins(\"LEFT OUTER JOIN statuses_tags t#{id} ON t#{id}.status_id = statuses.id AND t#{id}.tag_id = #{id}\")",
       "render_path": null,
@@ -159,22 +143,43 @@
       "note": ""
     },
     {
-      "warning_type": "Dynamic Render Path",
-      "warning_code": 15,
-      "fingerprint": "8d843713d99e8403f7992f3e72251b633817cf9076ffcbbad5613859d2bbc127",
-      "check_name": "Render",
-      "message": "Render path contains parameter value",
-      "file": "app/views/admin/custom_emojis/index.html.haml",
-      "line": 45,
-      "link": "https://brakemanscanner.org/docs/warning_types/dynamic_render_path/",
-      "code": "render(action => filtered_custom_emojis.eager_load(:local_counterpart).page(params[:page]), {})",
-      "render_path": [{"type":"controller","class":"Admin::CustomEmojisController","method":"index","line":11,"file":"app/controllers/admin/custom_emojis_controller.rb","rendered":{"name":"admin/custom_emojis/index","file":"/home/eugr/Projects/mastodon/app/views/admin/custom_emojis/index.html.haml"}}],
+      "warning_type": "Mass Assignment",
+      "warning_code": 105,
+      "fingerprint": "7631e93d0099506e7c3e5c91ba8d88523b00a41a0834ae30031a5a4e8bb3020a",
+      "check_name": "PermitAttributes",
+      "message": "Potentially dangerous key allowed for mass assignment",
+      "file": "app/controllers/api/v2/search_controller.rb",
+      "line": 28,
+      "link": "https://brakemanscanner.org/docs/warning_types/mass_assignment/",
+      "code": "params.permit(:type, :offset, :min_id, :max_id, :account_id)",
+      "render_path": null,
       "location": {
-        "type": "template",
-        "template": "admin/custom_emojis/index"
+        "type": "method",
+        "class": "Api::V2::SearchController",
+        "method": "search_params"
       },
-      "user_input": "params[:page]",
-      "confidence": "Weak",
+      "user_input": ":account_id",
+      "confidence": "High",
+      "note": ""
+    },
+    {
+      "warning_type": "Mass Assignment",
+      "warning_code": 105,
+      "fingerprint": "8f63dec68951d9bcf7eddb15af9392b2e1333003089c41fb76688dfd3579f394",
+      "check_name": "PermitAttributes",
+      "message": "Potentially dangerous key allowed for mass assignment",
+      "file": "app/controllers/api/v1/crypto/deliveries_controller.rb",
+      "line": 23,
+      "link": "https://brakemanscanner.org/docs/warning_types/mass_assignment/",
+      "code": "params.require(:device).permit(:account_id, :device_id, :type, :body, :hmac)",
+      "render_path": null,
+      "location": {
+        "type": "method",
+        "class": "Api::V1::Crypto::DeliveriesController",
+        "method": "resource_params"
+      },
+      "user_input": ":account_id",
+      "confidence": "High",
       "note": ""
     },
     {
@@ -204,10 +209,22 @@
       "check_name": "Render",
       "message": "Render path contains parameter value",
       "file": "app/views/admin/accounts/index.html.haml",
-      "line": 47,
+      "line": 54,
       "link": "https://brakemanscanner.org/docs/warning_types/dynamic_render_path/",
       "code": "render(action => filtered_accounts.page(params[:page]), {})",
-      "render_path": [{"type":"controller","class":"Admin::AccountsController","method":"index","line":12,"file":"app/controllers/admin/accounts_controller.rb","rendered":{"name":"admin/accounts/index","file":"/home/eugr/Projects/mastodon/app/views/admin/accounts/index.html.haml"}}],
+      "render_path": [
+        {
+          "type": "controller",
+          "class": "Admin::AccountsController",
+          "method": "index",
+          "line": 12,
+          "file": "app/controllers/admin/accounts_controller.rb",
+          "rendered": {
+            "name": "admin/accounts/index",
+            "file": "app/views/admin/accounts/index.html.haml"
+          }
+        }
+      ],
       "location": {
         "type": "template",
         "template": "admin/accounts/index"
@@ -219,40 +236,40 @@
     {
       "warning_type": "Redirect",
       "warning_code": 18,
-      "fingerprint": "ba699ddcc6552c422c4ecd50d2cd217f616a2446659e185a50b05a0f2dad8d33",
+      "fingerprint": "ba568ac09683f98740f663f3d850c31785900215992e8c090497d359a2563d50",
       "check_name": "Redirect",
       "message": "Possible unprotected redirect",
-      "file": "app/controllers/media_controller.rb",
-      "line": 14,
+      "file": "app/controllers/remote_follow_controller.rb",
+      "line": 21,
       "link": "https://brakemanscanner.org/docs/warning_types/redirect/",
-      "code": "redirect_to(MediaAttachment.attached.find_by!(:shortcode => ((params[:id] or params[:medium_id]))).file.url(:original))",
+      "code": "redirect_to(RemoteFollow.new(resource_params).subscribe_address_for(@account))",
       "render_path": null,
       "location": {
         "type": "method",
-        "class": "MediaController",
-        "method": "show"
+        "class": "RemoteFollowController",
+        "method": "create"
       },
-      "user_input": "MediaAttachment.attached.find_by!(:shortcode => ((params[:id] or params[:medium_id]))).file.url(:original)",
+      "user_input": "RemoteFollow.new(resource_params).subscribe_address_for(@account)",
       "confidence": "High",
       "note": ""
     },
     {
       "warning_type": "Redirect",
       "warning_code": 18,
-      "fingerprint": "bb7e94e60af41decb811bb32171f1b27e9bf3f4d01e9e511127362e22510eb11",
+      "fingerprint": "ba699ddcc6552c422c4ecd50d2cd217f616a2446659e185a50b05a0f2dad8d33",
       "check_name": "Redirect",
       "message": "Possible unprotected redirect",
-      "file": "app/controllers/remote_follow_controller.rb",
-      "line": 19,
+      "file": "app/controllers/media_controller.rb",
+      "line": 20,
       "link": "https://brakemanscanner.org/docs/warning_types/redirect/",
-      "code": "redirect_to(RemoteFollow.new(resource_params).subscribe_address_for(Account.find_local!(params[:account_username])))",
+      "code": "redirect_to(MediaAttachment.attached.find_by!(:shortcode => ((params[:id] or params[:medium_id]))).file.url(:original))",
       "render_path": null,
       "location": {
         "type": "method",
-        "class": "RemoteFollowController",
-        "method": "create"
+        "class": "MediaController",
+        "method": "show"
       },
-      "user_input": "RemoteFollow.new(resource_params).subscribe_address_for(Account.find_local!(params[:account_username]))",
+      "user_input": "MediaAttachment.attached.find_by!(:shortcode => ((params[:id] or params[:medium_id]))).file.url(:original)",
       "confidence": "High",
       "note": ""
     },
@@ -275,27 +292,8 @@
       "user_input": ":account_id",
       "confidence": "High",
       "note": ""
-    },
-    {
-      "warning_type": "Dynamic Render Path",
-      "warning_code": 15,
-      "fingerprint": "fbd0fc59adb5c6d44b60e02debb31d3af11719f534c9881e21435bbff87404d6",
-      "check_name": "Render",
-      "message": "Render path contains parameter value",
-      "file": "app/views/stream_entries/show.html.haml",
-      "line": 23,
-      "link": "https://brakemanscanner.org/docs/warning_types/dynamic_render_path/",
-      "code": "render(partial => \"stream_entries/#{Account.find_local!(params[:account_username]).statuses.find(params[:id]).stream_entry.activity_type.downcase}\", { :locals => ({ Account.find_local!(params[:account_username]).statuses.find(params[:id]).stream_entry.activity_type.downcase.to_sym => Account.find_local!(params[:account_username]).statuses.find(params[:id]).stream_entry.activity, :include_threads => true }) })",
-      "render_path": [{"type":"controller","class":"StatusesController","method":"show","line":34,"file":"app/controllers/statuses_controller.rb","rendered":{"name":"stream_entries/show","file":"/home/eugr/Projects/mastodon/app/views/stream_entries/show.html.haml"}}],
-      "location": {
-        "type": "template",
-        "template": "stream_entries/show"
-      },
-      "user_input": "params[:id]",
-      "confidence": "Weak",
-      "note": ""
     }
   ],
-  "updated": "2019-02-21 02:30:29 +0100",
-  "brakeman_version": "4.4.0"
+  "updated": "2020-06-01 18:18:02 +0200",
+  "brakeman_version": "4.8.0"
 }
diff --git a/config/initializers/doorkeeper.rb b/config/initializers/doorkeeper.rb
index e03380cec..63cff7c59 100644
--- a/config/initializers/doorkeeper.rb
+++ b/config/initializers/doorkeeper.rb
@@ -95,7 +95,8 @@ Doorkeeper.configure do
                   :'admin:read:reports',
                   :'admin:write',
                   :'admin:write:accounts',
-                  :'admin:write:reports'
+                  :'admin:write:reports',
+                  :crypto
 
   # Change the way client credentials are retrieved from the request object.
   # By default it retrieves first from the `HTTP_AUTHORIZATION` header, then
diff --git a/config/initializers/inflections.rb b/config/initializers/inflections.rb
index 0667a542c..ebb7541eb 100644
--- a/config/initializers/inflections.rb
+++ b/config/initializers/inflections.rb
@@ -19,6 +19,7 @@ ActiveSupport::Inflector.inflections(:en) do |inflect|
   inflect.acronym 'ActivityStreams'
   inflect.acronym 'JsonLd'
   inflect.acronym 'NodeInfo'
+  inflect.acronym 'Ed25519'
 
   inflect.singular 'data', 'data'
 end
diff --git a/config/locales/en.yml b/config/locales/en.yml
index 116db4498..aed96e3e1 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -35,13 +35,16 @@ en:
     status_count_before: Who authored
     tagline: Follow friends and discover new ones
     terms: Terms of service
-    unavailable_content: Unavailable content
+    unavailable_content: Moderated servers
     unavailable_content_description:
       domain: Server
       reason: Reason
       rejecting_media: 'Media files from these servers will not be processed or stored, and no thumbnails will be displayed, requiring manual click-through to the original file:'
-      silenced: 'Posts from these servers will be hidden in public timelines and conversations, and no notifications will be generated from their users'' interactions, unless you are following them:'
+      rejecting_media_title: Filtered media
+      silenced: 'Posts from these servers will be hidden in public timelines and conversations, and no notifications will be generated from their users interactions, unless you are following them:'
+      silenced_title: Silenced servers
       suspended: 'No data from these servers will be processed, stored or exchanged, making any interaction or communication with users from these servers impossible:'
+      suspended_title: Suspended servers
     unavailable_content_html: Mastodon generally allows you to view content from and interact with users from any other server in the fediverse. These are the exceptions that have been made on this particular server.
     user_count_after:
       one: user
@@ -309,6 +312,7 @@ en:
       listed: Listed
       new:
         title: Add new custom emoji
+      not_permitted: You are not permitted to perform this action
       overwrite: Overwrite
       shortcode: Shortcode
       shortcode_hint: At least 2 characters, only alphanumeric characters and underscores
@@ -721,6 +725,10 @@ en:
     hint_html: "<strong>Tip:</strong> We won't ask you for your password again for the next hour."
     invalid_password: Invalid password
     prompt: Confirm password to continue
+  crypto:
+    errors:
+      invalid_key: is not a valid Ed25519 or Curve25519 key
+      invalid_signature: is not a valid Ed25519 signature
   date:
     formats:
       default: "%b %d, %Y"
@@ -918,6 +926,7 @@ en:
     on_cooldown: You have recently migrated your account. This function will become available again in %{count} days.
     past_migrations: Past migrations
     proceed_with_move: Move followers
+    redirected_msg: Your account is now redirecting to %{acct}.
     redirecting_to: Your account is redirecting to %{acct}.
     set_redirect: Set redirect
     warning:
@@ -1267,6 +1276,12 @@ en:
       explanation: You requested a full backup of your Mastodon account. It's now ready for download!
       subject: Your archive is ready for download
       title: Archive takeout
+    sign_in_token:
+      details: 'Here are details of the attempt:'
+      explanation: 'We detected an attempt to sign in to your account from an unrecognized IP address. If this is you, please enter the security code below on the sign in challenge page:'
+      further_actions: 'If this wasn''t you, please change your password and enable two-factor authentication on your account. You can do so here:'
+      subject: Please confirm attempted sign in
+      title: Sign in attempt
     warning:
       explanation:
         disable: While your account is frozen, your account data remains intact, but you cannot perform any actions until it is unlocked.
@@ -1304,11 +1319,14 @@ en:
       title: Welcome aboard, %{name}!
   users:
     follow_limit_reached: You cannot follow more than %{limit} people
+    generic_access_help_html: Trouble accessing your account? You may get in touch with %{email} for assistance
     invalid_email: The e-mail address is invalid
     invalid_otp_token: Invalid two-factor code
+    invalid_sign_in_token: Invalid security code
     otp_lost_help_html: If you lost access to both, you may get in touch with %{email}
     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:'
+    suspicious_sign_in_confirmation: You appear to not have logged in from this device before, and you haven't logged in for a while, so we're sending a security code to your e-mail address to confirm that it's you.
   verification:
     explanation_html: 'You can <strong>verify yourself as the owner of the links in your profile metadata</strong>. For that, the linked website must contain a link back to your Mastodon profile. The link back <strong>must</strong> have a <code>rel="me"</code> attribute. The text content of the link does not matter. Here is an example:'
     verification: Verification
diff --git a/config/locales/simple_form.en.yml b/config/locales/simple_form.en.yml
index fd56a35bf..f84b6c884 100644
--- a/config/locales/simple_form.en.yml
+++ b/config/locales/simple_form.en.yml
@@ -151,6 +151,7 @@ en:
         setting_use_blurhash: Show colorful gradients for hidden media
         setting_use_pending_items: Slow mode
         severity: Severity
+        sign_in_token_attempt: Security code
         type: Import type
         username: Username
         username_or_email: Username or Email
diff --git a/config/routes.rb b/config/routes.rb
index 42f2f0f7f..93e995df2 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -79,6 +79,7 @@ Rails.application.routes.draw do
 
     resource :outbox, only: [:show], module: :activitypub
     resource :inbox, only: [:create], module: :activitypub
+    resource :claim, only: [:create], module: :activitypub
     resources :collections, only: [:show], module: :activitypub
   end
 
@@ -342,6 +343,23 @@ Rails.application.routes.draw do
         end
       end
 
+      namespace :crypto do
+        resources :deliveries, only: :create
+
+        namespace :keys do
+          resource :upload, only: [:create]
+          resource :query,  only: [:create]
+          resource :claim,  only: [:create]
+          resource :count,  only: [:show]
+        end
+
+        resources :encrypted_messages, only: [:index] do
+          collection do
+            post :clear
+          end
+        end
+      end
+
       resources :conversations, only: [:index, :destroy] do
         member do
           post :read
diff --git a/config/webpack/shared.js b/config/webpack/shared.js
index 08526957b..36b5a459e 100644
--- a/config/webpack/shared.js
+++ b/config/webpack/shared.js
@@ -110,10 +110,12 @@ module.exports = {
       writeToDisk: true,
       publicPath: true,
     }),
-    new CopyPlugin([
-      { from: 'node_modules/tesseract.js/dist/worker.min.js', to: 'ocr' },
-      { from: 'node_modules/tesseract.js-core/tesseract-core.wasm.js', to: 'ocr' },
-    ]),
+    new CopyPlugin({
+      patterns: [
+        { from: 'node_modules/tesseract.js/dist/worker.min.js', to: 'ocr' },
+        { from: 'node_modules/tesseract.js-core/tesseract-core.wasm.js', to: 'ocr' },
+      ],
+    }),
   ],
 
   resolve: {