diff --git a/app/controllers/api/internal/users/deletions_controller.rb b/app/controllers/api/internal/users/deletions_controller.rb new file mode 100644 index 000000000..8b6ca379c --- /dev/null +++ b/app/controllers/api/internal/users/deletions_controller.rb @@ -0,0 +1,52 @@ +# frozen_string_literal: true + +module Api + module Internal + module Users + class DeletionsController < ApplicationController + protect_from_forgery with: :exception + before_action :authenticate_request! + + def create + UserCleanupJob.perform_later( + params[:user_id] + ) + + head :ok + end + + private + + def authenticate_request! + verify_token! + verify_signature! + end + + def verify_token! + token = request.headers['Authorization']&.remove('Bearer ') + + unless ActiveSupport::SecurityUtils.secure_compare( + token.to_s, + ENV.fetch('OPENHPI_API_TOKEN') + ) + return head :unauthorized + end + end + + def verify_signature! + expected = OpenSSL::HMAC.hexdigest( + 'SHA256', + ENV.fetch('OPENHPI_WEBHOOK_SECRET'), + request.raw_post + ) + + provided = request.headers['X-Signature'] + + unless ActiveSupport::SecurityUtils.secure_compare(expected, provided.to_s) + return head :unauthorized + end + end + end + end + end +end diff --git a/app/jobs/user_cleanup_job.rb b/app/jobs/user_cleanup_job.rb new file mode 100644 index 000000000..6391f9da7 --- /dev/null +++ b/app/jobs/user_cleanup_job.rb @@ -0,0 +1,21 @@ +# frozen_string_literal: true + +class UserCleanupJob < ApplicationJob + queue_as :default + + retry_on StandardError, wait: :exponentially_longer, attempts: 10 + + def perform(user_id) + cleanup_user_data(user_id) + end + + private + + def cleanup_user_data(user_id) + user = ExternalUser.find_by(external_id: user_id, consumer_id: 1) # Consumer with ID 1 is openHPI. + + if user.present? + user.update(name: 'Deleted User', email: nil) + end + end +end diff --git a/config/routes.rb b/config/routes.rb index 9a5e8b154..05ce1ff00 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -193,6 +193,14 @@ mount ActionCable.server => '/cable' mount RailsAdmin::Engine => '/rails_admin', as: 'rails_admin' + namespace :api do + namespace :internal do + namespace :users do + post 'deleted', to: 'deletions#create' + end + end + end + # Reveal health status on /up that returns 200 if the app boots with no exceptions, otherwise 500. # Can be used by load balancers and uptime monitors to verify that the app is live. get 'up', to: 'rails/health#show', as: :rails_health_check