From c17dbfbcc7ce0f1dcab0f901c4d6d17fb1e98e1f Mon Sep 17 00:00:00 2001 From: Justin Edmund Date: Mon, 15 Dec 2025 16:09:02 -0800 Subject: [PATCH] add download_image endpoint for job skills --- app/blueprints/api/v1/job_skill_blueprint.rb | 2 +- .../api/v1/job_skills_controller.rb | 59 +++++++++++++++++++ config/routes.rb | 4 ++ 3 files changed, 64 insertions(+), 1 deletion(-) diff --git a/app/blueprints/api/v1/job_skill_blueprint.rb b/app/blueprints/api/v1/job_skill_blueprint.rb index b6b79b1..2d52380 100644 --- a/app/blueprints/api/v1/job_skill_blueprint.rb +++ b/app/blueprints/api/v1/job_skill_blueprint.rb @@ -14,7 +14,7 @@ module Api name: :job, blueprint: JobBlueprint - fields :slug, :color, :main, :base, :sub, :emp, :order + fields :slug, :color, :main, :base, :sub, :emp, :order, :image_id, :action_id end end end diff --git a/app/controllers/api/v1/job_skills_controller.rb b/app/controllers/api/v1/job_skills_controller.rb index 2bee31e..16c47ea 100644 --- a/app/controllers/api/v1/job_skills_controller.rb +++ b/app/controllers/api/v1/job_skills_controller.rb @@ -3,6 +3,9 @@ module Api module V1 class JobSkillsController < Api::V1::ApiController + before_action :doorkeeper_authorize!, only: %i[create update destroy download_image] + before_action :ensure_editor_role, only: %i[create update destroy download_image] + def all render json: JobSkillBlueprint.render(JobSkill.includes(:job).all) end @@ -25,6 +28,62 @@ module Api .where(emp: true) render json: JobSkillBlueprint.render(@skills) end + + # POST /jobs/:job_id/skills + def create + job = Job.find_by(granblue_id: params[:job_id]) + return render_not_found_response('job') unless job + + skill = job.skills.build(job_skill_params) + if skill.save + render json: JobSkillBlueprint.render(skill), status: :created + else + render_validation_error_response(skill) + end + end + + # PUT /jobs/:job_id/skills/:id + def update + skill = JobSkill.find(params[:id]) + if skill.update(job_skill_params) + render json: JobSkillBlueprint.render(skill) + else + render_validation_error_response(skill) + end + end + + # DELETE /jobs/:job_id/skills/:id + def destroy + skill = JobSkill.find(params[:id]) + skill.destroy + head :no_content + end + + # POST /jobs/:job_id/skills/:id/download_image + def download_image + skill = JobSkill.find(params[:id]) + return render json: { error: 'No image_id' }, status: :unprocessable_entity unless skill.image_id.present? + return render json: { error: 'No slug' }, status: :unprocessable_entity unless skill.slug.present? + + downloader = Granblue::Downloaders::JobSkillDownloader.new(skill.image_id, slug: skill.slug, storage: :s3) + result = downloader.download + + render json: { success: result[:success], filename: "#{skill.slug}.png" } + end + + private + + def job_skill_params + params.permit(:name_en, :name_jp, :slug, :color, :main, :base, :sub, :emp, :order, + :image_id, :action_id) + end + + def ensure_editor_role + return if current_user&.role && current_user.role >= 7 + + Rails.logger.warn "[JOB_SKILLS] Unauthorized access attempt by user #{current_user&.id}" + render json: { error: 'Unauthorized - Editor role required' }, status: :unauthorized + end end end end diff --git a/config/routes.rb b/config/routes.rb index 0f3969c..3b670af 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -91,6 +91,10 @@ Rails.application.routes.draw do put 'jobs/:id', to: 'jobs#update' get 'jobs/:id/skills', to: 'job_skills#job' get 'jobs/:id/emp_skills', to: 'job_skills#emp' + post 'jobs/:job_id/skills', to: 'job_skills#create' + put 'jobs/:job_id/skills/:id', to: 'job_skills#update' + delete 'jobs/:job_id/skills/:id', to: 'job_skills#destroy' + post 'jobs/:job_id/skills/:id/download_image', to: 'job_skills#download_image' get 'jobs/:id/accessories', to: 'job_accessories#job' get 'characters/:id/related', to: 'characters#related'