add artifact controllers and routes
This commit is contained in:
parent
069118cbe9
commit
cc7ac1956b
5 changed files with 343 additions and 0 deletions
29
app/controllers/api/v1/artifact_skills_controller.rb
Normal file
29
app/controllers/api/v1/artifact_skills_controller.rb
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module Api
|
||||||
|
module V1
|
||||||
|
class ArtifactSkillsController < Api::V1::ApiController
|
||||||
|
# GET /artifact_skills
|
||||||
|
def index
|
||||||
|
@skills = ArtifactSkill.all
|
||||||
|
@skills = @skills.where(skill_group: params[:group]) if params[:group].present?
|
||||||
|
@skills = @skills.where(polarity: params[:polarity]) if params[:polarity].present?
|
||||||
|
|
||||||
|
render json: ArtifactSkillBlueprint.render(@skills, root: :artifact_skills)
|
||||||
|
end
|
||||||
|
|
||||||
|
# GET /artifact_skills/for_slot/:slot
|
||||||
|
# Returns skills valid for a specific slot (1-4)
|
||||||
|
def for_slot
|
||||||
|
slot = params[:slot].to_i
|
||||||
|
|
||||||
|
unless (1..4).cover?(slot)
|
||||||
|
return render json: { error: 'Slot must be between 1 and 4' }, status: :unprocessable_entity
|
||||||
|
end
|
||||||
|
|
||||||
|
@skills = ArtifactSkill.for_slot(slot)
|
||||||
|
render json: ArtifactSkillBlueprint.render(@skills, root: :artifact_skills)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
31
app/controllers/api/v1/artifacts_controller.rb
Normal file
31
app/controllers/api/v1/artifacts_controller.rb
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module Api
|
||||||
|
module V1
|
||||||
|
class ArtifactsController < Api::V1::ApiController
|
||||||
|
before_action :set_artifact, only: [:show]
|
||||||
|
|
||||||
|
# GET /artifacts
|
||||||
|
def index
|
||||||
|
@artifacts = Artifact.all
|
||||||
|
@artifacts = @artifacts.where(rarity: params[:rarity]) if params[:rarity].present?
|
||||||
|
@artifacts = @artifacts.where(proficiency: params[:proficiency]) if params[:proficiency].present?
|
||||||
|
|
||||||
|
render json: ArtifactBlueprint.render(@artifacts, root: :artifacts)
|
||||||
|
end
|
||||||
|
|
||||||
|
# GET /artifacts/:id
|
||||||
|
def show
|
||||||
|
render json: ArtifactBlueprint.render(@artifact)
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def set_artifact
|
||||||
|
@artifact = Artifact.find(params[:id])
|
||||||
|
rescue ActiveRecord::RecordNotFound
|
||||||
|
render_not_found_response('artifact')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
147
app/controllers/api/v1/collection_artifacts_controller.rb
Normal file
147
app/controllers/api/v1/collection_artifacts_controller.rb
Normal file
|
|
@ -0,0 +1,147 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module Api
|
||||||
|
module V1
|
||||||
|
class CollectionArtifactsController < ApiController
|
||||||
|
# Read actions: look up user from params, check privacy
|
||||||
|
before_action :set_target_user, only: %i[index show]
|
||||||
|
before_action :check_collection_access, only: %i[index show]
|
||||||
|
before_action :set_collection_artifact_for_read, only: %i[show]
|
||||||
|
|
||||||
|
# Write actions: require auth, use current_user
|
||||||
|
before_action :restrict_access, only: %i[create update destroy batch]
|
||||||
|
before_action :set_collection_artifact_for_write, only: %i[update destroy]
|
||||||
|
|
||||||
|
def index
|
||||||
|
@collection_artifacts = @target_user.collection_artifacts.includes(:artifact)
|
||||||
|
|
||||||
|
@collection_artifacts = @collection_artifacts.where(artifact_id: params[:artifact_id]) if params[:artifact_id]
|
||||||
|
@collection_artifacts = @collection_artifacts.where(element: params[:element]) if params[:element]
|
||||||
|
|
||||||
|
@collection_artifacts = @collection_artifacts.paginate(page: params[:page], per_page: params[:limit] || 50)
|
||||||
|
|
||||||
|
render json: Api::V1::CollectionArtifactBlueprint.render(
|
||||||
|
@collection_artifacts,
|
||||||
|
root: :artifacts,
|
||||||
|
meta: pagination_meta(@collection_artifacts)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def show
|
||||||
|
render json: Api::V1::CollectionArtifactBlueprint.render(
|
||||||
|
@collection_artifact,
|
||||||
|
view: :full
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def create
|
||||||
|
@collection_artifact = current_user.collection_artifacts.build(collection_artifact_params)
|
||||||
|
|
||||||
|
if @collection_artifact.save
|
||||||
|
render json: Api::V1::CollectionArtifactBlueprint.render(
|
||||||
|
@collection_artifact,
|
||||||
|
view: :full
|
||||||
|
), status: :created
|
||||||
|
else
|
||||||
|
render_validation_error_response(@collection_artifact)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def update
|
||||||
|
if @collection_artifact.update(collection_artifact_params)
|
||||||
|
render json: Api::V1::CollectionArtifactBlueprint.render(
|
||||||
|
@collection_artifact,
|
||||||
|
view: :full
|
||||||
|
)
|
||||||
|
else
|
||||||
|
render_validation_error_response(@collection_artifact)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def destroy
|
||||||
|
@collection_artifact.destroy
|
||||||
|
head :no_content
|
||||||
|
end
|
||||||
|
|
||||||
|
# POST /collection/artifacts/batch
|
||||||
|
# Creates multiple collection artifacts in a single request
|
||||||
|
def batch
|
||||||
|
items = batch_artifact_params[:collection_artifacts] || []
|
||||||
|
created = []
|
||||||
|
errors = []
|
||||||
|
|
||||||
|
ActiveRecord::Base.transaction do
|
||||||
|
items.each_with_index do |item_params, index|
|
||||||
|
collection_artifact = current_user.collection_artifacts.build(item_params)
|
||||||
|
|
||||||
|
if collection_artifact.save
|
||||||
|
created << collection_artifact
|
||||||
|
else
|
||||||
|
errors << {
|
||||||
|
index: index,
|
||||||
|
artifact_id: item_params[:artifact_id],
|
||||||
|
error: collection_artifact.errors.full_messages.join(', ')
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
status = errors.any? ? :multi_status : :created
|
||||||
|
|
||||||
|
render json: Api::V1::CollectionArtifactBlueprint.render(
|
||||||
|
created,
|
||||||
|
root: :artifacts,
|
||||||
|
meta: { created: created.size, errors: errors }
|
||||||
|
), status: status
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def set_target_user
|
||||||
|
@target_user = User.find(params[:user_id])
|
||||||
|
rescue ActiveRecord::RecordNotFound
|
||||||
|
render json: { error: 'User not found' }, status: :not_found
|
||||||
|
end
|
||||||
|
|
||||||
|
def check_collection_access
|
||||||
|
return if @target_user.nil?
|
||||||
|
|
||||||
|
return if @target_user.collection_viewable_by?(current_user)
|
||||||
|
|
||||||
|
render json: { error: 'You do not have permission to view this collection' }, status: :forbidden
|
||||||
|
end
|
||||||
|
|
||||||
|
def set_collection_artifact_for_read
|
||||||
|
@collection_artifact = @target_user.collection_artifacts.find(params[:id])
|
||||||
|
rescue ActiveRecord::RecordNotFound
|
||||||
|
raise CollectionErrors::CollectionItemNotFound.new('artifact', params[:id])
|
||||||
|
end
|
||||||
|
|
||||||
|
def set_collection_artifact_for_write
|
||||||
|
@collection_artifact = current_user.collection_artifacts.find(params[:id])
|
||||||
|
rescue ActiveRecord::RecordNotFound
|
||||||
|
raise CollectionErrors::CollectionItemNotFound.new('artifact', params[:id])
|
||||||
|
end
|
||||||
|
|
||||||
|
def collection_artifact_params
|
||||||
|
params.require(:collection_artifact).permit(
|
||||||
|
:artifact_id, :element, :proficiency, :level, :nickname,
|
||||||
|
skill1: %i[modifier strength level],
|
||||||
|
skill2: %i[modifier strength level],
|
||||||
|
skill3: %i[modifier strength level],
|
||||||
|
skill4: %i[modifier strength level]
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def batch_artifact_params
|
||||||
|
params.permit(collection_artifacts: [
|
||||||
|
:artifact_id, :element, :proficiency, :level, :nickname,
|
||||||
|
{ skill1: %i[modifier strength level] },
|
||||||
|
{ skill2: %i[modifier strength level] },
|
||||||
|
{ skill3: %i[modifier strength level] },
|
||||||
|
{ skill4: %i[modifier strength level] }
|
||||||
|
])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
119
app/controllers/api/v1/grid_artifacts_controller.rb
Normal file
119
app/controllers/api/v1/grid_artifacts_controller.rb
Normal file
|
|
@ -0,0 +1,119 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module Api
|
||||||
|
module V1
|
||||||
|
class GridArtifactsController < Api::V1::ApiController
|
||||||
|
before_action :find_grid_artifact, only: %i[update destroy]
|
||||||
|
before_action :find_party, only: %i[create update destroy]
|
||||||
|
before_action :find_grid_character, only: %i[create]
|
||||||
|
before_action :find_artifact, only: %i[create]
|
||||||
|
before_action :authorize_party_edit!, only: %i[create update destroy]
|
||||||
|
|
||||||
|
# POST /grid_artifacts
|
||||||
|
def create
|
||||||
|
# Check if grid_character already has an artifact
|
||||||
|
if @grid_character.grid_artifact.present?
|
||||||
|
@grid_character.grid_artifact.destroy
|
||||||
|
end
|
||||||
|
|
||||||
|
@grid_artifact = GridArtifact.new(
|
||||||
|
grid_artifact_params.merge(
|
||||||
|
grid_character_id: @grid_character.id,
|
||||||
|
artifact_id: @artifact.id
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
if @grid_artifact.save
|
||||||
|
render json: GridArtifactBlueprint.render(@grid_artifact, view: :nested, root: :grid_artifact), status: :created
|
||||||
|
else
|
||||||
|
render_validation_error_response(@grid_artifact)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# PATCH/PUT /grid_artifacts/:id
|
||||||
|
def update
|
||||||
|
if @grid_artifact.update(grid_artifact_params)
|
||||||
|
render json: GridArtifactBlueprint.render(@grid_artifact, view: :nested, root: :grid_artifact), status: :ok
|
||||||
|
else
|
||||||
|
render_validation_error_response(@grid_artifact)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# DELETE /grid_artifacts/:id
|
||||||
|
def destroy
|
||||||
|
if @grid_artifact.destroy
|
||||||
|
render json: GridArtifactBlueprint.render(@grid_artifact, view: :destroyed), status: :ok
|
||||||
|
else
|
||||||
|
render_unprocessable_entity_response(
|
||||||
|
Api::V1::GranblueError.new(@grid_artifact.errors.full_messages.join(', '))
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def find_grid_artifact
|
||||||
|
@grid_artifact = GridArtifact.find_by(id: params[:id])
|
||||||
|
render_not_found_response('grid_artifact') unless @grid_artifact
|
||||||
|
end
|
||||||
|
|
||||||
|
def find_party
|
||||||
|
@party = if @grid_artifact
|
||||||
|
@grid_artifact.grid_character.party
|
||||||
|
else
|
||||||
|
Party.find_by(id: params[:party_id])
|
||||||
|
end
|
||||||
|
render_not_found_response('party') unless @party
|
||||||
|
end
|
||||||
|
|
||||||
|
def find_grid_character
|
||||||
|
@grid_character = GridCharacter.find_by(id: params.dig(:grid_artifact, :grid_character_id))
|
||||||
|
render_not_found_response('grid_character') unless @grid_character
|
||||||
|
end
|
||||||
|
|
||||||
|
def find_artifact
|
||||||
|
artifact_id = params.dig(:grid_artifact, :artifact_id)
|
||||||
|
@artifact = Artifact.find_by(id: artifact_id)
|
||||||
|
render_not_found_response('artifact') unless @artifact
|
||||||
|
end
|
||||||
|
|
||||||
|
def authorize_party_edit!
|
||||||
|
if @party.user.present?
|
||||||
|
authorize_user_party
|
||||||
|
else
|
||||||
|
authorize_anonymous_party
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def authorize_user_party
|
||||||
|
return if current_user.present? && @party.user == current_user
|
||||||
|
|
||||||
|
render_unauthorized_response
|
||||||
|
end
|
||||||
|
|
||||||
|
def authorize_anonymous_party
|
||||||
|
provided_edit_key = edit_key.to_s.strip.force_encoding('UTF-8')
|
||||||
|
party_edit_key = @party.edit_key.to_s.strip.force_encoding('UTF-8')
|
||||||
|
return if valid_edit_key?(provided_edit_key, party_edit_key)
|
||||||
|
|
||||||
|
render_unauthorized_response
|
||||||
|
end
|
||||||
|
|
||||||
|
def valid_edit_key?(provided_edit_key, party_edit_key)
|
||||||
|
provided_edit_key.present? &&
|
||||||
|
provided_edit_key.bytesize == party_edit_key.bytesize &&
|
||||||
|
ActiveSupport::SecurityUtils.secure_compare(provided_edit_key, party_edit_key)
|
||||||
|
end
|
||||||
|
|
||||||
|
def grid_artifact_params
|
||||||
|
params.require(:grid_artifact).permit(
|
||||||
|
:grid_character_id, :artifact_id, :element, :proficiency, :level,
|
||||||
|
skill1: %i[modifier strength level],
|
||||||
|
skill2: %i[modifier strength level],
|
||||||
|
skill3: %i[modifier strength level],
|
||||||
|
skill4: %i[modifier strength level]
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -101,6 +101,17 @@ Rails.application.routes.draw do
|
||||||
|
|
||||||
resources :weapon_series, only: %i[index show create update destroy]
|
resources :weapon_series, only: %i[index show create update destroy]
|
||||||
|
|
||||||
|
# Artifacts (read-only reference data)
|
||||||
|
resources :artifacts, only: %i[index show]
|
||||||
|
resources :artifact_skills, only: %i[index] do
|
||||||
|
collection do
|
||||||
|
get 'for_slot/:slot', action: :for_slot, as: :for_slot
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Grid artifacts
|
||||||
|
resources :grid_artifacts, only: %i[create update destroy]
|
||||||
|
|
||||||
# Grid endpoints - new prefixed versions
|
# Grid endpoints - new prefixed versions
|
||||||
post 'grid_characters/resolve', to: 'grid_characters#resolve'
|
post 'grid_characters/resolve', to: 'grid_characters#resolve'
|
||||||
post 'grid_characters/update_uncap', to: 'grid_characters#update_uncap_level'
|
post 'grid_characters/update_uncap', to: 'grid_characters#update_uncap_level'
|
||||||
|
|
@ -134,6 +145,7 @@ Rails.application.routes.draw do
|
||||||
resources :characters, only: [:index, :show], controller: '/api/v1/collection_characters'
|
resources :characters, only: [:index, :show], controller: '/api/v1/collection_characters'
|
||||||
resources :weapons, only: [:index, :show], controller: '/api/v1/collection_weapons'
|
resources :weapons, only: [:index, :show], controller: '/api/v1/collection_weapons'
|
||||||
resources :summons, only: [:index, :show], controller: '/api/v1/collection_summons'
|
resources :summons, only: [:index, :show], controller: '/api/v1/collection_summons'
|
||||||
|
resources :artifacts, only: [:index, :show], controller: '/api/v1/collection_artifacts'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -156,6 +168,11 @@ Rails.application.routes.draw do
|
||||||
end
|
end
|
||||||
resources :job_accessories, controller: '/api/v1/collection_job_accessories',
|
resources :job_accessories, controller: '/api/v1/collection_job_accessories',
|
||||||
only: [:index, :show, :create, :destroy]
|
only: [:index, :show, :create, :destroy]
|
||||||
|
resources :artifacts, only: [:create, :update, :destroy], controller: '/api/v1/collection_artifacts' do
|
||||||
|
collection do
|
||||||
|
post :batch
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue