about summary refs log tree commit diff
path: root/app/controllers/api/v1/crypto
diff options
context:
space:
mode:
authorEugen Rochko <eugen@zeonfederated.com>2020-06-02 19:24:53 +0200
committerGitHub <noreply@github.com>2020-06-02 19:24:53 +0200
commit5d8398c8b8b51ee7363e7d45acc560f489783e34 (patch)
tree1e0b663049feafdc003ad3c01b25bf5d5d793402 /app/controllers/api/v1/crypto
parent9b7e3b4774d47c184aa759364d41f40e0cdfa210 (diff)
Add E2EE API (#13820)
Diffstat (limited to 'app/controllers/api/v1/crypto')
-rw-r--r--app/controllers/api/v1/crypto/deliveries_controller.rb30
-rw-r--r--app/controllers/api/v1/crypto/encrypted_messages_controller.rb59
-rw-r--r--app/controllers/api/v1/crypto/keys/claims_controller.rb25
-rw-r--r--app/controllers/api/v1/crypto/keys/counts_controller.rb17
-rw-r--r--app/controllers/api/v1/crypto/keys/queries_controller.rb26
-rw-r--r--app/controllers/api/v1/crypto/keys/uploads_controller.rb29
6 files changed, 186 insertions, 0 deletions
diff --git a/app/controllers/api/v1/crypto/deliveries_controller.rb b/app/controllers/api/v1/crypto/deliveries_controller.rb
new file mode 100644
index 000000000..aa9df6e03
--- /dev/null
+++ b/app/controllers/api/v1/crypto/deliveries_controller.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+class Api::V1::Crypto::DeliveriesController < Api::BaseController
+  before_action -> { doorkeeper_authorize! :crypto }
+  before_action :require_user!
+  before_action :set_current_device
+
+  def create
+    devices.each do |device_params|
+      DeliverToDeviceService.new.call(current_account, @current_device, device_params)
+    end
+
+    render_empty
+  end
+
+  private
+
+  def set_current_device
+    @current_device = Device.find_by!(access_token: doorkeeper_token)
+  end
+
+  def resource_params
+    params.require(:device)
+    params.permit(device: [:account_id, :device_id, :type, :body, :hmac])
+  end
+
+  def devices
+    Array(resource_params[:device])
+  end
+end
diff --git a/app/controllers/api/v1/crypto/encrypted_messages_controller.rb b/app/controllers/api/v1/crypto/encrypted_messages_controller.rb
new file mode 100644
index 000000000..a67b03eb4
--- /dev/null
+++ b/app/controllers/api/v1/crypto/encrypted_messages_controller.rb
@@ -0,0 +1,59 @@
+# frozen_string_literal: true
+
+class Api::V1::Crypto::EncryptedMessagesController < Api::BaseController
+  LIMIT = 80
+
+  before_action -> { doorkeeper_authorize! :crypto }
+  before_action :require_user!
+  before_action :set_current_device
+
+  before_action :set_encrypted_messages,    only: :index
+  after_action  :insert_pagination_headers, only: :index
+
+  def index
+    render json: @encrypted_messages, each_serializer: REST::EncryptedMessageSerializer
+  end
+
+  def clear
+    @current_device.encrypted_messages.up_to(params[:up_to_id]).delete_all
+    render_empty
+  end
+
+  private
+
+  def set_current_device
+    @current_device = Device.find_by!(access_token: doorkeeper_token)
+  end
+
+  def set_encrypted_messages
+    @encrypted_messages = @current_device.encrypted_messages.paginate_by_id(limit_param(LIMIT), params_slice(:max_id, :since_id, :min_id))
+  end
+
+  def insert_pagination_headers
+    set_pagination_headers(next_path, prev_path)
+  end
+
+  def next_path
+    api_v1_encrypted_messages_url pagination_params(max_id: pagination_max_id) if records_continue?
+  end
+
+  def prev_path
+    api_v1_encrypted_messages_url pagination_params(min_id: pagination_since_id) unless @encrypted_messages.empty?
+  end
+
+  def pagination_max_id
+    @encrypted_messages.last.id
+  end
+
+  def pagination_since_id
+    @encrypted_messages.first.id
+  end
+
+  def records_continue?
+    @encrypted_messages.size == limit_param(LIMIT)
+  end
+
+  def pagination_params(core_params)
+    params.slice(:limit).permit(:limit).merge(core_params)
+  end
+end
diff --git a/app/controllers/api/v1/crypto/keys/claims_controller.rb b/app/controllers/api/v1/crypto/keys/claims_controller.rb
new file mode 100644
index 000000000..34b21a380
--- /dev/null
+++ b/app/controllers/api/v1/crypto/keys/claims_controller.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+class Api::V1::Crypto::Keys::ClaimsController < Api::BaseController
+  before_action -> { doorkeeper_authorize! :crypto }
+  before_action :require_user!
+  before_action :set_claim_results
+
+  def create
+    render json: @claim_results, each_serializer: REST::Keys::ClaimResultSerializer
+  end
+
+  private
+
+  def set_claim_results
+    @claim_results = devices.map { |device_params| ::Keys::ClaimService.new.call(current_account, device_params[:account_id], device_params[:device_id]) }.compact
+  end
+
+  def resource_params
+    params.permit(device: [:account_id, :device_id])
+  end
+
+  def devices
+    Array(resource_params[:device])
+  end
+end
diff --git a/app/controllers/api/v1/crypto/keys/counts_controller.rb b/app/controllers/api/v1/crypto/keys/counts_controller.rb
new file mode 100644
index 000000000..ffd7151b7
--- /dev/null
+++ b/app/controllers/api/v1/crypto/keys/counts_controller.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class Api::V1::Crypto::Keys::CountsController < Api::BaseController
+  before_action -> { doorkeeper_authorize! :crypto }
+  before_action :require_user!
+  before_action :set_current_device
+
+  def show
+    render json: { one_time_keys: @current_device.one_time_keys.count }
+  end
+
+  private
+
+  def set_current_device
+    @current_device = Device.find_by!(access_token: doorkeeper_token)
+  end
+end
diff --git a/app/controllers/api/v1/crypto/keys/queries_controller.rb b/app/controllers/api/v1/crypto/keys/queries_controller.rb
new file mode 100644
index 000000000..0851d797d
--- /dev/null
+++ b/app/controllers/api/v1/crypto/keys/queries_controller.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+class Api::V1::Crypto::Keys::QueriesController < Api::BaseController
+  before_action -> { doorkeeper_authorize! :crypto }
+  before_action :require_user!
+  before_action :set_accounts
+  before_action :set_query_results
+
+  def create
+    render json: @query_results, each_serializer: REST::Keys::QueryResultSerializer
+  end
+
+  private
+
+  def set_accounts
+    @accounts = Account.where(id: account_ids).includes(:devices)
+  end
+
+  def set_query_results
+    @query_results = @accounts.map { |account| ::Keys::QueryService.new.call(account) }.compact
+  end
+
+  def account_ids
+    Array(params[:id]).map(&:to_i)
+  end
+end
diff --git a/app/controllers/api/v1/crypto/keys/uploads_controller.rb b/app/controllers/api/v1/crypto/keys/uploads_controller.rb
new file mode 100644
index 000000000..fc4abf63b
--- /dev/null
+++ b/app/controllers/api/v1/crypto/keys/uploads_controller.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+class Api::V1::Crypto::Keys::UploadsController < Api::BaseController
+  before_action -> { doorkeeper_authorize! :crypto }
+  before_action :require_user!
+
+  def create
+    device = Device.find_or_initialize_by(access_token: doorkeeper_token)
+
+    device.transaction do
+      device.account = current_account
+      device.update!(resource_params[:device])
+
+      if resource_params[:one_time_keys].present? && resource_params[:one_time_keys].is_a?(Enumerable)
+        resource_params[:one_time_keys].each do |one_time_key_params|
+          device.one_time_keys.create!(one_time_key_params)
+        end
+      end
+    end
+
+    render json: device, serializer: REST::Keys::DeviceSerializer
+  end
+
+  private
+
+  def resource_params
+    params.permit(device: [:device_id, :name, :fingerprint_key, :identity_key], one_time_keys: [:key_id, :key, :signature])
+  end
+end