diff --git a/config/routes.rb b/config/routes.rb index 004a940a3..d5013fb6f 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -555,6 +555,11 @@ Rails.application.routes.draw do end resources :email_channel_migrations, only: [:create] end + if ChatwootApp.enterprise? + namespace :internal do + resources :accounts, only: [:index] + end + end end end end diff --git a/enterprise/app/controllers/platform/api/v1/internal/accounts_controller.rb b/enterprise/app/controllers/platform/api/v1/internal/accounts_controller.rb new file mode 100644 index 000000000..da271a0e0 --- /dev/null +++ b/enterprise/app/controllers/platform/api/v1/internal/accounts_controller.rb @@ -0,0 +1,52 @@ +# frozen_string_literal: true + +class Platform::Api::V1::Internal::AccountsController < ActionController::API + include RequestExceptionHandler + + CONFIG_KEY = 'SIGNALS_PLATFORM_API_TOKEN' + DEFAULT_LIMIT = 100 + MAX_LIMIT = 1000 + + before_action :authenticate_internal_token! + + def index + @accounts = filtered_accounts.limit(limit) + end + + private + + def authenticate_internal_token! + return if internal_token.present? && secure_token_match?(request_token, internal_token) + + render json: { error: 'Invalid access_token' }, status: :unauthorized + end + + def request_token + bearer_token || request.headers[:api_access_token] || request.headers[:HTTP_API_ACCESS_TOKEN] + end + + def bearer_token + request.authorization&.split&.then { |scheme, token| token if scheme&.casecmp('Bearer')&.zero? } + end + + def internal_token + @internal_token ||= GlobalConfigService.load(CONFIG_KEY, nil) + end + + def secure_token_match?(token, configured_token) + return false if token.blank? || configured_token.blank? || token.bytesize != configured_token.bytesize + + ActiveSupport::SecurityUtils.secure_compare(token, configured_token) + end + + def filtered_accounts + scope = Account.order(:created_at, :id) + scope = scope.where('created_at >= ?', Time.zone.at(params[:since].to_i)) if params[:since].present? + scope = scope.where('created_at <= ?', Time.zone.at(params[:until].to_i)) if params[:until].present? + scope + end + + def limit + params.fetch(:limit, DEFAULT_LIMIT).to_i.clamp(1, MAX_LIMIT) + end +end diff --git a/enterprise/app/views/platform/api/v1/internal/accounts/index.json.jbuilder b/enterprise/app/views/platform/api/v1/internal/accounts/index.json.jbuilder new file mode 100644 index 000000000..445c0a8f0 --- /dev/null +++ b/enterprise/app/views/platform/api/v1/internal/accounts/index.json.jbuilder @@ -0,0 +1,11 @@ +json.array! @accounts do |account| + json.id account.id + json.name account.name + json.created_at account.created_at + json.updated_at account.updated_at + json.status account.status + json.plan_name account.custom_attributes['plan_name'] + json.custom_attributes account.custom_attributes + json.limits account.limits + json.marketing_attribution account.internal_attributes['marketing_attribution'] +end