Skip to content

Commit

Permalink
Merge pull request #224 from hsong-rh/primay_id_validation
Browse files Browse the repository at this point in the history
  • Loading branch information
lindgrenj6 authored May 14, 2021
2 parents b53ab53 + 5fa9b95 commit 246a6f7
Show file tree
Hide file tree
Showing 10 changed files with 237 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,14 @@ module ClassMethods
private

def id_regexp(primary_collection_name)
@id_regexp ||= begin
@id_regexp_table ||= {}

if @id_regexp_table.empty? || @id_regexp_table[primary_collection_name].nil?
id_parameter = id_parameter_from_api_doc(primary_collection_name)
id_parameter ? id_parameter.fetch_path("schema", "pattern") : /^\d+$/
@id_regexp_table[primary_collection_name] = id_parameter ? id_parameter.fetch_path("schema", "pattern") : /^\d+$/
end

@id_regexp_table[primary_collection_name]
end

def id_parameter_from_api_doc(primary_collection_name)
Expand Down
11 changes: 11 additions & 0 deletions spec/dummy/app/controllers/api/v2/tasks_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
module Api
module V2
class TasksController < ApplicationController
include Api::V2::Mixins::IndexMixin

def show
render :json => Task.find(params[:id]).to_json
end
end
end
end
1 change: 1 addition & 0 deletions spec/dummy/app/controllers/api/v2x0.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,6 @@ class ErrorsController < Api::V1x0::ErrorsController; end
class GraphqlController < Api::V2::GraphqlController; end
class SourcesController < Api::V2::SourcesController; end
class SourceTypesController < Api::V2::SourceTypesController; end
class TasksController < Api::V2::TasksController; end
end
end
1 change: 1 addition & 0 deletions spec/dummy/app/models/source.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ class Source < ApplicationRecord
has_many :applications
has_many :application_types, :through => :applications
has_many :endpoints, :autosave => true
has_many :tasks

belongs_to :source_type

Expand Down
4 changes: 4 additions & 0 deletions spec/dummy/app/models/task.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
class Task < ApplicationRecord
include TenancyConcern
belongs_to :source
end
5 changes: 4 additions & 1 deletion spec/dummy/config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,11 @@
resources :authentications, :only => [:create, :update]
resources :vms, :only => [:index, :show]
resources :persons, :only => [:index, :create, :show, :update]
resources :sources, :only => [:index]
resources :sources, :only => [:index] do
resources :tasks, :only => [:index]
end
resources :source_types, :only => [:index]
resources :tasks, :only => [:index, :show]
resources :extras, :only => [:index]
end

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
class EnablePgcryptoExtension < ActiveRecord::Migration[5.2]
def change
enable_extension 'uuid-ossp'
enable_extension 'pgcrypto'
end
end
12 changes: 12 additions & 0 deletions spec/dummy/db/migrate/20210429134638_create_tasks.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
class CreateTasks < ActiveRecord::Migration[5.2]
def change
create_table :tasks, :id => :uuid do |t|
t.references :tenant, :index => true, :null => false
t.references :source, :index => true, :null => true, :foreign_key => {:on_delete => :nullify}
t.string :name
t.string :status
t.string :state
t.string :message
end
end
end
172 changes: 172 additions & 0 deletions spec/dummy/public/doc/openapi-3-v2.0.0.json
Original file line number Diff line number Diff line change
Expand Up @@ -669,6 +669,105 @@
}
}
},
"/sources/{id}/tasks": {
"get": {
"summary": "List Tasks for Source",
"operationId": "listSourceTasks",
"description": "Returns an array of Task objects",
"parameters": [
{
"$ref": "#/components/parameters/QueryLimit"
},
{
"$ref": "#/components/parameters/QueryOffset"
},
{
"$ref": "#/components/parameters/QueryFilter"
},
{
"$ref": "#/components/parameters/QuerySortBy"
},
{
"$ref": "#/components/parameters/ID"
}
],
"responses": {
"200": {
"description": "Tasks collection",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/TasksCollection"
}
}
}
}
}
}
},
"/tasks": {
"get": {
"summary": "List Tasks",
"operationId": "listTasks",
"description": "Returns an array of Task objects",
"parameters": [
{
"$ref": "#/components/parameters/QueryLimit"
},
{
"$ref": "#/components/parameters/QueryOffset"
},
{
"$ref": "#/components/parameters/QueryFilter"
},
{
"$ref": "#/components/parameters/QuerySortBy"
},
{
"$ref": "#/components/parameters/ID"
}
],
"responses": {
"200": {
"description": "Tasks collection",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/TasksCollection"
}
}
}
}
}
}
},
"/tasks/{id}": {
"get": {
"summary": "Show an existing Task",
"operationId": "showTask",
"description": "Returns a Task object",
"parameters": [
{
"$ref": "#/components/parameters/UUID"
}
],
"responses": {
"200": {
"description": "Task info",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Task"
}
}
}
},
"404": {
"description": "Not found"
}
}
}
},
"/persons": {
"get": {
"summary": "List Person Objects",
Expand Down Expand Up @@ -913,6 +1012,16 @@
"type": "string",
"pattern": "^\\d+$"
}
},
"UUID": {
"name": "id",
"in": "path",
"description": "UUID of task",
"required": true,
"schema": {
"type": "string",
"pattern": "[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}"
}
}
},
"securitySchemes": {
Expand Down Expand Up @@ -1197,6 +1306,63 @@
}
}
},
"Task": {
"type": "object",
"properties": {
"id": {
"$ref": "#/components/schemas/UUID"
},
"name": {
"example": "OpenShift default",
"type": "string"
},
"status": {
"example": "valid",
"type": "string"
},
"state": {
"example": "complete",
"type": "string"
},
"message": {
"example": "Ready to go",
"type": "string"
},
"source_id": {
"$ref": "#/components/schemas/ID"
},
"tenant": {
"type": "string"
},
"created_at": {
"format": "date-time",
"readOnly": true,
"type": "string"
},
"updated_at": {
"format": "date-time",
"readOnly": true,
"type": "string"
}
}
},
"TasksCollection": {
"type": "object",
"properties": {
"meta": {
"$ref": "#/components/schemas/CollectionMetadata"
},
"links": {
"$ref": "#/components/schemas/CollectionLinks"
},
"data": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Task"
}
}
}
},
"GraphQLRequest": {
"type": "object",
"properties": {
Expand Down Expand Up @@ -1242,6 +1408,12 @@
"pattern": "^\\d+$",
"readOnly": true
},
"UUID": {
"type": "string",
"description": "UUID of the resource",
"format": "uuid",
"readOnly": true
},
"OrderParameters": {
"type": "object",
"properties": {
Expand Down
20 changes: 20 additions & 0 deletions spec/requests/request_path_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,24 @@
expect(response.status).to eq(400)
expect(response.parsed_body).to eq("errors" => [{"detail" => "Insights::API::Common::ApplicationControllerMixins::RequestPath::RequestPathError: ID is invalid", "status" => "400"}])
end

context "when object id pattern is different" do
let(:external_tenant) { rand(1000).to_s }
let(:tenant) { Tenant.create!(:name => "default", :external_tenant => external_tenant) }
let(:source_type) { SourceType.create(:name => "AnsibleTower", :product_name => "RedHat AnsibleTower", :vendor => "redhat") }

before do
@source = Source.create!(:tenant => tenant, :name => "source_s1", :source_type => source_type)
@task = Task.create!(:tenant => tenant, :source => @source, :name => "Task_t1", :state => "pending")
end

it "valid ID" do
get "/api/v2.0/tasks/#{@task.id}"
get "/api/v2.0/sources/#{@source.id}/tasks"

expect(response.status).to eq(200)
expect(response.parsed_body["data"].count).to eq(1)
expect(response.parsed_body["data"].first["id"]).to eq(@task.id)
end
end
end

0 comments on commit 246a6f7

Please sign in to comment.