Commit 70511793 authored by charlie-ablett's avatar charlie-ablett
Browse files

Recipe step presets created from process steps. Simple recipe controller...

Recipe step presets created from process steps. Simple recipe controller action for increased efficiency/lazy loading. Updating tests to accommodate XSweet changes
parent a096182b
module Api
module V1
class RecipeStepPresetsController < ApplicationController
before_action :authenticate_account!, only: [:create, :update, :destroy]
before_action :authenticate!, only: [:index, :show]
# before_action :authenticate_account!, only: [:create, :update, :destroy, :creat_from_process_chain]
before_action :authenticate!
respond_to :json
def create_from_process_step
process_step = ProcessStep.find(params[:process_step_id])
process_chain = current_entity.account.process_chains.find(process_step.process_chain_id)
if process_chain.recipe.available_to_account?(current_entity.account)
new_recipe_step_preset.execution_parameters = process_step.execution_parameters
new_recipe_step_preset.recipe_step_id = process_chain.recipe.recipe_steps.find_by_position(process_step.position).id
new_recipe_step_preset.save!
render json: new_recipe_step_preset, scope: current_entity, scope_name: :current_entity
else
render json: "Recipe not available", status: 404
return
end
rescue => e
ap e.message
ap e.backtrace
render_error(e)
end
def create
if new_recipe_step_preset.recipe_step.recipe.available_to_account?(current_entity.account)
new_recipe_step_preset.execution_parameters = params[:recipe_step_preset][:execution_parameters]
......@@ -34,7 +52,7 @@ module Api
def show
if recipe_step_preset.recipe_step.recipe.available_to_account?(current_entity.account)
render json: recipe_step_preset, scope: current_entity, scope_name: :current_entity
render json: {presets: recipe_step_preset}, scope: current_entity, scope_name: :current_entity
else
render json: "Recipe not available", status: 404
end
......
......@@ -2,7 +2,7 @@ module Api
module V1
class RecipesController < ApplicationController
before_action :authenticate_account!, only: [:create, :update, :destroy, :favourite, :unfavourite, :favourites]
before_action :authenticate!, only: [:index, :show, :execute]
before_action :authenticate!, only: [:index, :show, :execute, :index_all]
respond_to :json
......@@ -47,10 +47,15 @@ module Api
render_error(e)
end
def index
def index_all
render json: recipes, scope: current_entity, scope_name: :current_entity
end
def index
@recipes = Recipe.available_to_account(current_entity.account.id, current_entity.admin?)
render json: @recipes, scope: current_entity, scope_name: :current_entity, each_serializer: SimpleRecipeSerializer
end
def favourites
render json: favourite_recipes, scope: current_entity, scope_name: :current_entity
end
......@@ -98,7 +103,12 @@ module Api
end
def execution_params
params[:execution_parameters] || {}
ex_params = params[:execution_parameters] || {}
if ex_params.is_a?(String)
return JSON.parse(ex_params)
else
ex_params
end
end
def callback_url_param
......@@ -114,7 +124,7 @@ module Api
end
def recipes
@recipes ||= Recipe.includes(:recipe_steps, process_chains: :process_steps).available_to_account(current_entity.account.id, current_entity.admin?)
@recipes ||= Recipe.includes(:recipe_steps, :recipe_favourites, process_chains: :process_steps).available_to_account(current_entity.account.id, current_entity.admin?)
end
def favourite_recipes
......
......@@ -80,7 +80,12 @@ class Recipe < ApplicationRecord
new_chain = process_chains.new(account: account, execution_parameters: execution_parameters)
recipe_steps.each do |recipe_step|
raw_params = execution_parameters[recipe_step.position.to_s] || {}
ap "Execution parameters"
ap execution_parameters
ap("raw param:", raw_params)
parameters = raw_params["data"] || {}
ap "param"
ap parameters
# Folding the ad-hoc execution parameters into the execution parameters detailed in the recipe step
# The ad-hoc parameters of the same name take precedence.
......@@ -154,8 +159,10 @@ class Recipe < ApplicationRecord
end
def available_to_account?(target_account)
return true if public? || account == target_account
return false if !active? && account != target_account
return true if target_account.admin?
return true if public?
return true if account == target_account
return false unless active? || account != target_account
false
end
......
class SimpleRecipeSerializer < ActiveModel::Serializer
attributes :id, :name, :description, :active, :account_id, :public, :recipe_steps, :favourite
def favourite
object.favourited_by?(scope)
end
end
\ No newline at end of file
......@@ -7,7 +7,7 @@ lock '3.4.1'
set :application, 'ink-api'
set :repo_url, 'git@gitlab.coko.foundation:INK/ink-api.git'
set :linked_files, fetch(:linked_files, []).push('config/database.yml', 'config/secrets.yml', 'config/ink_api.yml', '.env', 'StepGemfile')
set :linked_files, fetch(:linked_files, []).push('config/database.yml', 'config/secrets.yml', '.env', 'StepGemfile')#'config/ink_api.yml',
set :linked_dirs, fetch(:linked_dirs, []).push('log', 'tmp/pids', 'tmp/cache', 'tmp/sockets', 'vendor/bundle', 'public/system', 'public/uploads')
set :bundle_binstubs, nil
......
set :stage, :production
set :rails_env, 'production'
server '162.243.148.158', user: 'admin', roles: %w{web app}
set :deploy_to, '/home/admin/ink-api/production'
# server '162.243.148.158', user: 'admin', roles: %w{web app} #discourse
server '46.101.192.238', user: 'charlie', roles: %w{web app} #ink
set :deploy_to, '/home/ink-api/production'
set :branch, 'production'
# server-based syntax
......
......@@ -38,6 +38,7 @@ Rails.application.routes.draw do
resources :recipes, only: [:index, :show, :create, :update, :destroy] do
collection do
get 'favourites'
get 'index-all'
end
member do
......@@ -70,7 +71,11 @@ Rails.application.routes.draw do
resources :recipe_step_presets, only: [:index]
end
resources :recipe_step_presets, only: [:create, :update, :show, :destroy]
resources :recipe_step_presets, only: [:create, :update, :show, :destroy] do
collection do
post 'create_from_process_step'
end
end
end
# scope module: :v2, constraints: ApiConstraints.new(version: 2, default: true) do
......
......@@ -130,8 +130,8 @@ RSpec.describe Api::V1::RecipeStepPresetsController do
end
end
context 'if the recipe is invalid' do
context 'if the recipe is missing a field' do
context 'if the preset is invalid' do
context 'if the preset is missing a field' do
let(:invalid_preset_params) {
{
recipe_step_preset: {
......@@ -175,6 +175,113 @@ RSpec.describe Api::V1::RecipeStepPresetsController do
end
end
describe "POST create_from_process_step" do
let!(:execution_params) { { "tool" => "draw-knife", "wood" => "matai", "bird" => "South Island kōkako" } }
let!(:process_chain) { create(:process_chain, recipe: recipe, account: account) }
let!(:process_step) { create(:process_step, process_chain: process_chain, execution_parameters: execution_params) }
let(:preset_params) {
{
recipe_step_preset: {
name: new_name,
description: new_description
},
process_step_id: process_step.id
}
}
context 'if a valid token is supplied' do
context 'if the recipe step preset is valid' do
context "on another account's private recipe" do
before do
recipe.update_attribute(:account_id, other_account.id)
recipe.update_attribute(:public, false)
end
it 'does not allow it' do
request_with_auth(account.new_jwt) do
perform_create_from_process_step_request(preset_params)
end
expect(response.status).to eq 404
end
end
context 'and they are valid' do
it "creates the preset" do
request_with_auth(account.new_jwt) do
perform_create_from_process_step_request(preset_params)
end
expect(response.status).to eq 200
new_preset = assigns[:new_recipe_step_preset]
expect(new_preset).to be_a RecipeStepPreset
expect(new_preset.name).to eq new_name
expect(new_preset.description).to eq new_description
expect(new_preset.account).to eq account
expect(new_preset.execution_parameters).to eq execution_params
end
end
end
context 'if the preset is invalid' do
context 'if the preset is missing a field' do
let(:invalid_preset_params) {
{
recipe_step_preset: {
description: new_description,
recipe_step_id: recipe_step.id
},
process_step_id: process_step.id
}
}
it "is not successful" do
request_with_auth(account.new_jwt) do
perform_create_from_process_step_request(invalid_preset_params)
end
expect(response.status).to eq 422
expect(body_as_json['errors']).to eq ["Validation failed: Name can't be blank"]
end
end
context 'if the process chain does not belong to that account' do
before { process_chain.update_attribute(:account_id, other_account.id) }
it "is not successful" do
request_with_auth(account.new_jwt) do
perform_create_from_process_step_request(preset_params)
end
expect(response.status).to eq 404
end
end
end
end
context 'if no valid token is supplied' do
let(:preset_params) {
{
recipe_step_preset: {
name: new_name,
description: new_description,
execution_parameters: new_execution_parameters
}
}
}
it "does not assign anything" do
request_with_auth do
perform_create_from_process_step_request(preset_params)
end
expect(response.status).to eq 401
expect(assigns[:new_recipe_step_preset]).to be_nil
end
end
end
describe "GET index" do
context 'if a valid token is supplied' do
......@@ -451,6 +558,10 @@ RSpec.describe Api::V1::RecipeStepPresetsController do
post_create_request(version, data)
end
def perform_create_from_process_step_request(data = {})
post_create_from_chain_request(version, data)
end
def perform_update_request(data)
put_update_request(version, data)
end
......
......@@ -488,6 +488,12 @@ RSpec.describe Api::V1::RecipesController do
perform_index_request
end
ap "ACCOUNT"
ap account
ap "ADMIN? #{account.admin?}"
ap "ACCOUNT OWNS RECIPE ID #{recipe_1.id}"
ap "ACCOUNT DOES NOT OWN RECIPE ID #{recipe_2.id}"
expect(response.status).to eq 200
expect(assigns[:recipes].to_a).to eq [recipe_1, recipe_4]
end
......
......@@ -36,6 +36,9 @@ describe "Account executes a real recipe" do
with(headers: {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'User-Agent'=>'Ruby'}).
to_return(status: 200, body: File.read(Rails.root.join('spec/fixtures/files/xsweet_pipeline/docx-html-extract.xsl')), headers: {})
stub_request(:get, "https://gitlab.coko.foundation/atheg/XSweet/raw/master/applications/docx-extract/docx-html-extract.xsl").
with(headers: {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'User-Agent'=>'Ruby'}).
to_return(status: 200, body: "", headers: {})
end
context 'and execution is successful' do
......
......@@ -39,14 +39,19 @@ describe "Account executes a recipe xsweet pipeline" do
let(:step_1_xsl_file) { File.read(Rails.root.join('spec/fixtures/files/xsweet_pipeline/docx-html-extract.xsl')) }
let(:step_1_remote_uri) { "https://gitlab.coko.foundation/XSweet/XSweet/raw/ink-api-publish/applications/docx-extract/docx-html-extract.xsl" }
# let(:step_1_remote_uri) { "https://gitlab.coko.foundation/atheg/XSweet/raw/ink-api-publish/applications/docx-extract/docx-html-extract.xsl" }
let(:step_2_xsl_file) { File.read(Rails.root.join('spec/fixtures/files/xsweet_pipeline/handle-notes.xsl')) }
let(:step_2_remote_uri) { "https://gitlab.coko.foundation/XSweet/XSweet/raw/ink-api-publish/applications/docx-extract/handle-notes.xsl" }
# let(:step_2_remote_uri) { "https://gitlab.coko.foundation/atheg/XSweet/raw/ink-api-publish/applications/docx-extract/handle-notes.xsl" }
let(:step_3_xsl_file) { File.read(Rails.root.join('spec/fixtures/files/xsweet_pipeline/scrub.xsl')) }
let(:step_3_remote_uri) { "https://gitlab.coko.foundation/XSweet/XSweet/raw/ink-api-publish/applications/docx-extract/scrub.xsl" }
# let(:step_3_remote_uri) { "https://gitlab.coko.foundation/atheg/XSweet/raw/ink-api-publish/applications/docx-extract/scrub.xsl" }
let(:step_4_xsl_file) { File.read(Rails.root.join('spec/fixtures/files/xsweet_pipeline/join-elements.xsl')) }
let(:step_4_remote_uri) { "https://gitlab.coko.foundation/XSweet/XSweet/raw/ink-api-publish/applications/docx-extract/join-elements.xsl" }
# let(:step_4_remote_uri) { "https://gitlab.coko.foundation/atheg/XSweet/raw/ink-api-publish/applications/docx-extract/join-elements.xsl" }
let(:step_5_xsl_file) { File.read(Rails.root.join('spec/fixtures/files/xsweet_pipeline/collapse-paragraphs.xsl')) }
let(:step_5_remote_uri) { "https://gitlab.coko.foundation/XSweet/XSweet/raw/ink-api-publish/applications/docx-extract/collapse-paragraphs.xsl" }
# let(:step_5_remote_uri) { "https://gitlab.coko.foundation/atheg/XSweet/raw/ink-api-publish/applications/docx-extract/collapse-paragraphs.xsl" }
before do
stub_xsl_download(step_1_remote_uri, step_1_xsl_file)
......
......@@ -20,7 +20,6 @@ describe "Account lists all their recipes" do
let!(:other_recipe) { create(:recipe, account: other_account) }
context 'if account is signed in' do
context 'and there are some active recipes that belong to the account' do
before do
......@@ -43,6 +42,74 @@ describe "Account lists all their recipes" do
expect(body_as_json['recipes'][0]['public']).to eq recipe.public
end
end
context 'and there are no active recipes that belong to the current account' do
before do
recipe.destroy
perform_index_request(auth_headers)
end
it 'responds with success' do
expect(response.status).to eq(200)
end
it 'responds with an empty set' do
ap body_as_json
expect(body_as_json.to_a).to eq [['recipes', []]]
end
end
end
context 'if no account is signed in' do
before do
perform_index_request({})
end
it 'raises an error' do
expect(response.status).to eq(401)
end
it 'provides a message' do
expect_to_contain_string(body_as_json['errors'], /Authorized users only/)
end
end
end
describe "GET index_full" do
let!(:account) { create(:account, password: "password", password_confirmation: "password") }
let!(:other_account) { create(:account) }
let!(:auth_headers) { account.new_jwt }
let!(:recipe) { create(:recipe, account: account, step_classes: [rot_thirteen_step_class.to_s]) }
let!(:inactive_recipe) { create(:recipe, account: account, active: false) }
let!(:other_recipe) { create(:recipe, account: other_account) }
context 'if account is signed in' do
context 'and there are some active recipes that belong to the account' do
before do
perform_all_index_request(auth_headers)
end
it 'responds with success' do
expect(response.status).to eq(200)
end
it 'returns a list of Recipe objects' do
expect(body_as_json.count).to eq 1
ap body_as_json
expect(body_as_json['recipes'][0]['name']).to eq recipe.name
expect(body_as_json['recipes'][0]['description']).to eq recipe.description
expect(body_as_json['recipes'][0]['account_id']).to eq recipe.account.id
expect(body_as_json['recipes'][0]['active']).to eq recipe.active
expect(body_as_json['recipes'][0]['public']).to eq recipe.public
end
context 'and there are some steps and process chains' do
let!(:step1) { recipe.recipe_steps.first }
let!(:step2) { create(:recipe_step, recipe: recipe, position: 2, step_class_name: epub_calibre_step_class.to_s) }
......@@ -68,11 +135,7 @@ describe "Account lists all their recipes" do
end
it 'does not show them' do
perform_index_request(auth_headers)
ap "ACCOUNT OWNS PROCESS CHAIN ID #{process_chain1.id}"
ap "ACCOUNT DOES NOT OWN PROCESS CHAIN ID #{process_chain2.id}"
ap body_as_json['recipes'][0]['process_chains']
perform_all_index_request(auth_headers)
expect(body_as_json['recipes'][0]['process_chains'].count).to eq 1
expect(body_as_json['recipes'][0]['process_chains'][0]['id']).to eq process_chain1.id
......@@ -80,7 +143,7 @@ describe "Account lists all their recipes" do
end
it 'returns chain information in the right order' do
perform_index_request(auth_headers)
perform_all_index_request(auth_headers)
ap body_as_json
......@@ -92,7 +155,7 @@ describe "Account lists all their recipes" do
end
it 'gets the information correct' do
perform_index_request(auth_headers)
perform_all_index_request(auth_headers)
expect(body_as_json['recipes'][0]['process_chains'][0]['process_steps'][0]['position']).to eq 1
expect(body_as_json['recipes'][0]['process_chains'][0]['process_steps'][0]['step_class_name']).to eq process_step1a.step_class_name
......@@ -112,7 +175,7 @@ describe "Account lists all their recipes" do
before do
recipe.destroy
perform_index_request(auth_headers)
perform_all_index_request(auth_headers)
end
it 'responds with success' do
......@@ -129,7 +192,7 @@ describe "Account lists all their recipes" do
context 'if no account is signed in' do
before do
perform_index_request({})
perform_all_index_request({})
end
it 'raises an error' do
......@@ -144,7 +207,7 @@ describe "Account lists all their recipes" do
xcontext 'if the token has expired' do
before do
expire_token(account, auth_headers['client'])
perform_index_request({})
perform_all_index_request({})
end
it 'raises an error' do
......@@ -161,4 +224,8 @@ describe "Account lists all their recipes" do
def perform_index_request(auth_headers)
index_recipe_request(version, auth_headers)
end
def perform_all_index_request(auth_headers)
index_all_recipes_request(version, auth_headers)
end
end
\ No newline at end of file
......@@ -86,6 +86,12 @@ def get_index_by_gems_request(version, data = {}.to_json)
get :index_by_gems, params: data, headers: {'Content-Type' => "application/json", 'Accept' => "application/vnd.ink.#{version}" }
end
# recipe step preset controller requests
def post_create_from_chain_request(version, data = {}.to_json)
post :create_from_process_step, params: data, headers: {'Content-Type' => "application/json", 'Accept' => "application/vnd.ink.#{version}" }
end
# jwt auth authentication_controller requests
def post_sign_in_request(version, data = {}.to_json)
......
......@@ -37,3 +37,7 @@ def execute_recipe_request(version, auth_headers, data = {})
data.delete(:id)
post "/api/recipes/#{id}/execute", params: data, headers: {'Content-Type' => "application/json", 'Accept' => "application/vnd.ink.#{version}" }.merge(auth_headers)
end
def index_all_recipes_request(version, auth_headers)
get "/api/recipes/index-all", params: {}, headers: {'Content-Type' => "application/json", 'Accept' => "application/vnd.ink.#{version}" }.merge(auth_headers)
end
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment