From f53ffe8208e844e50d391a063949875ce5895b01 Mon Sep 17 00:00:00 2001 From: Justin Edmund Date: Sun, 2 Mar 2025 17:46:04 -0800 Subject: [PATCH] Add endpoints for importing game data This lets privileged users import canonical data for characters, weapons and summons directly from the game --- app/controllers/api/v1/import_controller.rb | 111 +++++++++++++++++++- config/routes.rb | 3 + 2 files changed, 111 insertions(+), 3 deletions(-) diff --git a/app/controllers/api/v1/import_controller.rb b/app/controllers/api/v1/import_controller.rb index 928768f..84f9e07 100644 --- a/app/controllers/api/v1/import_controller.rb +++ b/app/controllers/api/v1/import_controller.rb @@ -27,6 +27,8 @@ module Api 6 => 5 }.freeze + before_action :ensure_admin_role, only: %i[weapons summons characters] + ## # Processes an import request. # @@ -49,9 +51,9 @@ module Api end unless raw_params['deck'].is_a?(Hash) && - raw_params['deck'].key?('pc') && - raw_params['deck'].key?('npc') - Rails.logger.error "[IMPORT] Deck data incomplete or missing." + raw_params['deck'].key?('pc') && + raw_params['deck'].key?('npc') + Rails.logger.error '[IMPORT] Deck data incomplete or missing.' return render json: { error: 'Invalid deck data' }, status: :unprocessable_content end @@ -68,8 +70,111 @@ module Api render json: { error: e.message }, status: :unprocessable_content end + def weapons + Rails.logger.info '[IMPORT] Checking weapon gamedata input...' + + body = parse_request_body + return unless body + + weapon = Weapon.find_by(granblue_id: body['id']) + unless weapon + Rails.logger.error "[IMPORT] Weapon not found with ID: #{body['id']}" + return render json: { error: 'Weapon not found' }, status: :not_found + end + + lang = params[:lang] + unless %w[en jp].include?(lang) + Rails.logger.error "[IMPORT] Invalid language: #{lang}" + return render json: { error: 'Invalid language' }, status: :unprocessable_content + end + + begin + weapon.update!( + "game_raw_#{lang}" => body.to_json + ) + render json: { message: 'Weapon gamedata updated successfully' }, status: :ok + rescue StandardError => e + Rails.logger.error "[IMPORT] Failed to update weapon gamedata: #{e.message}" + render json: { error: e.message }, status: :unprocessable_content + end + end + + def summons + Rails.logger.info '[IMPORT] Checking summon gamedata input...' + + body = parse_request_body + return unless body + + summon = Summon.find_by(granblue_id: body['id']) + unless summon + Rails.logger.error "[IMPORT] Summon not found with ID: #{body['id']}" + return render json: { error: 'Summon not found' }, status: :not_found + end + + lang = params[:lang] + unless %w[en jp].include?(lang) + Rails.logger.error "[IMPORT] Invalid language: #{lang}" + return render json: { error: 'Invalid language' }, status: :unprocessable_content + end + + begin + summon.update!( + "game_raw_#{lang}" => body.to_json + ) + render json: { message: 'Summon gamedata updated successfully' }, status: :ok + rescue StandardError => e + Rails.logger.error "[IMPORT] Failed to update summon gamedata: #{e.message}" + render json: { error: e.message }, status: :unprocessable_content + end + end + + ## + # Updates character gamedata from JSON blob. + # + # @return [void] Renders JSON response with success or error message. + def characters + Rails.logger.info '[IMPORT] Checking character gamedata input...' + + body = parse_request_body + return unless body + + character = Character.find_by(granblue_id: body['id']) + unless character + Rails.logger.error "[IMPORT] Character not found with ID: #{body['id']}" + return render json: { error: 'Character not found' }, status: :not_found + end + + lang = params[:lang] + unless %w[en jp].include?(lang) + Rails.logger.error "[IMPORT] Invalid language: #{lang}" + return render json: { error: 'Invalid language' }, status: :unprocessable_content + end + + begin + character.update!( + "game_raw_#{lang}" => body.to_json + ) + render json: { message: 'Character gamedata updated successfully' }, status: :ok + rescue StandardError => e + Rails.logger.error "[IMPORT] Failed to update character gamedata: #{e.message}" + render json: { error: e.message }, status: :unprocessable_content + end + end + private + ## + # Ensures the current user has admin role (role 9). + # Renders an error if the user is not an admin. + # + # @return [void] + def ensure_admin_role + return if current_user&.role == 9 + + Rails.logger.error "[IMPORT] Unauthorized access attempt by user #{current_user&.id}" + render json: { error: 'Unauthorized' }, status: :unauthorized + end + ## # Reads and parses the raw JSON request body. # diff --git a/config/routes.rb b/config/routes.rb index fafbf95..7523e2e 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -20,6 +20,9 @@ Rails.application.routes.draw do get 'version', to: 'api#version' post 'import', to: 'import#create' + post 'import/weapons', to: 'import#weapons' + post 'import/summons', to: 'import#summons' + post 'import/characters', to: 'import#characters' get 'users/info/:id', to: 'users#info'