diff --git a/Gemfile b/Gemfile index ead69aa..cb91e69 100644 --- a/Gemfile +++ b/Gemfile @@ -21,6 +21,7 @@ gem 'rack-cors' gem 'react-rails' gem 'rubytree' gem 'acts_as_tenant' +gem 'httparty' group :development, :test do gem 'annotaterb' diff --git a/Gemfile.lock b/Gemfile.lock index 7e795fc..c0660de 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -126,6 +126,10 @@ GEM raabro (~> 1.4) globalid (1.2.1) activesupport (>= 6.1) + httparty (0.22.0) + csv + mini_mime (>= 1.0.0) + multi_xml (>= 0.5.2) i18n (1.14.6) concurrent-ruby (~> 1.0) importmap-rails (2.0.3) @@ -188,6 +192,8 @@ GEM money (6.19.0) i18n (>= 0.6.4, <= 2) msgpack (1.7.2) + multi_xml (0.7.1) + bigdecimal (~> 3.1) net-imap (0.5.1) date net-protocol @@ -398,6 +404,7 @@ DEPENDENCIES devise (~> 4.9) factory_bot_rails faker + httparty importmap-rails jbuilder jsonapi-rails diff --git a/app/controllers/captcha_controller.rb b/app/controllers/captcha_controller.rb new file mode 100644 index 0000000..79f84ea --- /dev/null +++ b/app/controllers/captcha_controller.rb @@ -0,0 +1,11 @@ +class CaptchaController < ApplicationController + skip_before_action :authenticate_user! + + def create + id = LibreCaptcha.new.get_id + render json: { + id:, + media_url: media_captcha_index_url(id:) + }, status: :created + end +end diff --git a/app/services/libre_captcha.rb b/app/services/libre_captcha.rb new file mode 100644 index 0000000..3d49e5a --- /dev/null +++ b/app/services/libre_captcha.rb @@ -0,0 +1,12 @@ +class LibreCaptcha + def get_id + HTTParty.post("http://libre-captcha:8888/v2/captcha", + body: { + input_type: "text", + level: :hard, + media: 'image/png', + size: '350x100' + }.to_json + ).then { |raw| JSON.parse(raw)['id'] } + end +end \ No newline at end of file diff --git a/config/routes.rb b/config/routes.rb index 10810fe..1357d9c 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -23,6 +23,9 @@ Rails.application.routes.draw do resources :tables_arrangements, only: %i[index show] end + resources :captcha, only: :create do + get 'v2/media', to: 'captcha#media', on: :collection, as: :media + end mount Rswag::Ui::Engine => '/api-docs' mount Rswag::Api::Engine => '/api-docs' diff --git a/docker-compose.yml b/docker-compose.yml index e1a5977..18050d1 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -36,6 +36,12 @@ services: - backend volumes: - ../wedding-planner-frontend/:/app + libre-captcha: + image: librecaptcha/lc-core:latest + volumes: + - "./tmp/libre-captcha-data:/lc-core/data" + ports: + - "8888:8888" nginx: image: nginx:latest ports: diff --git a/nginx.conf b/nginx.conf index 06d059b..6371bdd 100644 --- a/nginx.conf +++ b/nginx.conf @@ -12,6 +12,11 @@ server { proxy_set_header Host $http_host; } + location /captcha/ { + proxy_pass http://libre-captcha:8888/; + proxy_set_header Host $http_host; + } + location / { proxy_pass http://frontend:3000; proxy_set_header Host $http_host; diff --git a/spec/requests/captcha_spec.rb b/spec/requests/captcha_spec.rb new file mode 100644 index 0000000..adac1a8 --- /dev/null +++ b/spec/requests/captcha_spec.rb @@ -0,0 +1,22 @@ +require 'swagger_helper' + +RSpec.describe 'captcha', type: :request do + path '/captcha' do + + post('create a CAPTCHA challenge') do + tags 'CAPTCHA' + consumes 'application/json' + produces 'application/json' + + response(201, 'created') do + schema type: :object, + required: %i[id], + properties: { + id: { type: :string, format: :uuid } + media_url: { type: :string, format: :uri } + } + xit + end + end + end +end