mirror of
https://github.com/Freika/dawarich.git
synced 2026-01-09 08:47:11 -05:00
Add swagger along with api/v1/points swagger doc
This commit is contained in:
parent
5e46168cf8
commit
e488dc9e4a
14 changed files with 285 additions and 7 deletions
|
|
@ -2,3 +2,12 @@ require: rubocop-rails
|
||||||
|
|
||||||
Style/Documentation:
|
Style/Documentation:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
|
||||||
|
Style/ClassAndModuleChildren:
|
||||||
|
Enabled: false
|
||||||
|
|
||||||
|
Layout/HashAlignment:
|
||||||
|
Enabled: false
|
||||||
|
|
||||||
|
Metrics/BlockLength:
|
||||||
|
Enabled: false
|
||||||
|
|
|
||||||
3
Gemfile
3
Gemfile
|
|
@ -13,6 +13,8 @@ gem 'pg'
|
||||||
gem 'puma'
|
gem 'puma'
|
||||||
gem 'pundit'
|
gem 'pundit'
|
||||||
gem 'rails'
|
gem 'rails'
|
||||||
|
gem 'rswag-api'
|
||||||
|
gem 'rswag-ui'
|
||||||
gem 'shrine', '~> 3.6'
|
gem 'shrine', '~> 3.6'
|
||||||
gem 'sidekiq'
|
gem 'sidekiq'
|
||||||
gem 'sidekiq-cron'
|
gem 'sidekiq-cron'
|
||||||
|
|
@ -30,6 +32,7 @@ group :development, :test do
|
||||||
gem 'pry-byebug'
|
gem 'pry-byebug'
|
||||||
gem 'pry-rails'
|
gem 'pry-rails'
|
||||||
gem 'rspec-rails'
|
gem 'rspec-rails'
|
||||||
|
gem 'rswag-specs'
|
||||||
end
|
end
|
||||||
|
|
||||||
group :test do
|
group :test do
|
||||||
|
|
|
||||||
16
Gemfile.lock
16
Gemfile.lock
|
|
@ -145,6 +145,8 @@ GEM
|
||||||
rdoc (>= 4.0.0)
|
rdoc (>= 4.0.0)
|
||||||
reline (>= 0.4.2)
|
reline (>= 0.4.2)
|
||||||
json (2.7.2)
|
json (2.7.2)
|
||||||
|
json-schema (4.3.0)
|
||||||
|
addressable (>= 2.8)
|
||||||
language_server-protocol (3.17.0.3)
|
language_server-protocol (3.17.0.3)
|
||||||
loofah (2.22.0)
|
loofah (2.22.0)
|
||||||
crass (~> 1.0.2)
|
crass (~> 1.0.2)
|
||||||
|
|
@ -277,6 +279,17 @@ GEM
|
||||||
rspec-mocks (~> 3.13)
|
rspec-mocks (~> 3.13)
|
||||||
rspec-support (~> 3.13)
|
rspec-support (~> 3.13)
|
||||||
rspec-support (3.13.1)
|
rspec-support (3.13.1)
|
||||||
|
rswag-api (2.13.0)
|
||||||
|
activesupport (>= 3.1, < 7.2)
|
||||||
|
railties (>= 3.1, < 7.2)
|
||||||
|
rswag-specs (2.13.0)
|
||||||
|
activesupport (>= 3.1, < 7.2)
|
||||||
|
json-schema (>= 2.2, < 5.0)
|
||||||
|
railties (>= 3.1, < 7.2)
|
||||||
|
rspec-core (>= 2.14)
|
||||||
|
rswag-ui (2.13.0)
|
||||||
|
actionpack (>= 3.1, < 7.2)
|
||||||
|
railties (>= 3.1, < 7.2)
|
||||||
rubocop (1.62.1)
|
rubocop (1.62.1)
|
||||||
json (~> 2.3)
|
json (~> 2.3)
|
||||||
language_server-protocol (>= 3.17.0)
|
language_server-protocol (>= 3.17.0)
|
||||||
|
|
@ -390,6 +403,9 @@ DEPENDENCIES
|
||||||
rails
|
rails
|
||||||
redis
|
redis
|
||||||
rspec-rails
|
rspec-rails
|
||||||
|
rswag-api
|
||||||
|
rswag-specs
|
||||||
|
rswag-ui
|
||||||
rubocop-rails
|
rubocop-rails
|
||||||
shoulda-matchers
|
shoulda-matchers
|
||||||
shrine (~> 3.6)
|
shrine (~> 3.6)
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class Api::V1::PointsController < ApplicationController
|
class Api::V1::PointsController < ApplicationController
|
||||||
skip_forgery_protection
|
skip_forgery_protection
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,11 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class Owntracks::PointCreatingJob < ApplicationJob
|
class Owntracks::PointCreatingJob < ApplicationJob
|
||||||
queue_as :default
|
queue_as :default
|
||||||
|
|
||||||
def perform(point_params)
|
def perform(point_params)
|
||||||
parsed_params = OwnTracks::Params.new(point_params).call
|
parsed_params = OwnTracks::Params.new(point_params).call
|
||||||
|
|
||||||
point = Point.create(parsed_params)
|
Point.create(parsed_params)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
14
config/initializers/rswag_api.rb
Normal file
14
config/initializers/rswag_api.rb
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
Rswag::Api.configure do |c|
|
||||||
|
|
||||||
|
# Specify a root folder where Swagger JSON files are located
|
||||||
|
# This is used by the Swagger middleware to serve requests for API descriptions
|
||||||
|
# NOTE: If you're using rswag-specs to generate Swagger, you'll need to ensure
|
||||||
|
# that it's configured to generate files in the same folder
|
||||||
|
c.openapi_root = Rails.root.to_s + '/swagger'
|
||||||
|
|
||||||
|
# Inject a lambda function to alter the returned Swagger prior to serialization
|
||||||
|
# The function will have access to the rack env for the current request
|
||||||
|
# For example, you could leverage this to dynamically assign the "host" property
|
||||||
|
#
|
||||||
|
#c.swagger_filter = lambda { |swagger, env| swagger['host'] = env['HTTP_HOST'] }
|
||||||
|
end
|
||||||
16
config/initializers/rswag_ui.rb
Normal file
16
config/initializers/rswag_ui.rb
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
Rswag::Ui.configure do |c|
|
||||||
|
|
||||||
|
# List the Swagger endpoints that you want to be documented through the
|
||||||
|
# swagger-ui. The first parameter is the path (absolute or relative to the UI
|
||||||
|
# host) to the corresponding endpoint and the second is a title that will be
|
||||||
|
# displayed in the document selector.
|
||||||
|
# NOTE: If you're using rspec-api to expose Swagger files
|
||||||
|
# (under openapi_root) as JSON or YAML endpoints, then the list below should
|
||||||
|
# correspond to the relative paths for those endpoints.
|
||||||
|
|
||||||
|
c.swagger_endpoint '/api-docs/v1/swagger.yaml', 'API V1 Docs'
|
||||||
|
|
||||||
|
# Add Basic Auth in case your API is private
|
||||||
|
# c.basic_auth_enabled = true
|
||||||
|
# c.basic_auth_credentials 'username', 'password'
|
||||||
|
end
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
Rails.application.routes.draw do
|
Rails.application.routes.draw do
|
||||||
|
mount Rswag::Api::Engine => '/api-docs'
|
||||||
|
mount Rswag::Ui::Engine => '/api-docs'
|
||||||
get 'settings/theme', to: 'settings#theme'
|
get 'settings/theme', to: 'settings#theme'
|
||||||
get 'export', to: 'export#index'
|
get 'export', to: 'export#index'
|
||||||
get 'export/download', to: 'export#download'
|
get 'export/download', to: 'export#download'
|
||||||
|
|
|
||||||
8
lib/tasks/rswag.rake
Normal file
8
lib/tasks/rswag.rake
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
namespace :rswag do
|
||||||
|
desc 'Generate Swagger docs'
|
||||||
|
task generate: [:environment] do
|
||||||
|
system 'bundle exec rake rswag:specs:swaggerize PATTERN="spec/swagger/**/*_spec.rb"'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -6,6 +6,11 @@ require_relative '../config/environment'
|
||||||
|
|
||||||
abort('The Rails environment is running in production mode!') if Rails.env.production?
|
abort('The Rails environment is running in production mode!') if Rails.env.production?
|
||||||
require 'rspec/rails'
|
require 'rspec/rails'
|
||||||
|
require 'rswag/specs'
|
||||||
|
|
||||||
|
require 'rake'
|
||||||
|
|
||||||
|
Rails.application.load_tasks
|
||||||
# Add additional requires below this line. Rails is not loaded until this point!
|
# Add additional requires below this line. Rails is not loaded until this point!
|
||||||
|
|
||||||
Dir[Rails.root.join('spec/support/**/*.rb')].sort.each { |f| require f }
|
Dir[Rails.root.join('spec/support/**/*.rb')].sort.each { |f| require f }
|
||||||
|
|
@ -27,9 +32,15 @@ RSpec.configure do |config|
|
||||||
config.include FactoryBot::Syntax::Methods
|
config.include FactoryBot::Syntax::Methods
|
||||||
config.include Devise::Test::IntegrationHelpers, type: :request
|
config.include Devise::Test::IntegrationHelpers, type: :request
|
||||||
|
|
||||||
|
config.rswag_dry_run = false
|
||||||
|
|
||||||
config.before do
|
config.before do
|
||||||
ActiveJob::Base.queue_adapter = :test
|
ActiveJob::Base.queue_adapter = :test
|
||||||
end
|
end
|
||||||
|
|
||||||
|
config.after(:suite) do
|
||||||
|
Rake::Task['rswag:generate'].invoke
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
Shoulda::Matchers.configure do |config|
|
Shoulda::Matchers.configure do |config|
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,24 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require 'rails_helper'
|
require 'rails_helper'
|
||||||
|
|
||||||
RSpec.describe "Api::V1::Points", type: :request do
|
RSpec.describe 'Api::V1::Points', type: :request do
|
||||||
describe "POST /api/v1/points" do
|
describe 'POST /api/v1/points' do
|
||||||
context 'with valid params' do
|
context 'with valid params' do
|
||||||
let(:params) do
|
let(:params) do
|
||||||
{ lat: 1.0, lon: 1.0, tid: 'test', tst: Time.now.to_i, topic: 'iPhone 12 pro' }
|
{ lat: 1.0, lon: 1.0, tid: 'test', tst: Time.current.to_i, topic: 'iPhone 12 pro' }
|
||||||
end
|
end
|
||||||
|
|
||||||
it "returns http success" do
|
it 'returns http success' do
|
||||||
post api_v1_points_path, params: params
|
post api_v1_points_path, params: params
|
||||||
|
|
||||||
expect(response).to have_http_status(:success)
|
expect(response).to have_http_status(:success)
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'enqueues a job' do
|
it 'enqueues a job' do
|
||||||
expect {
|
expect do
|
||||||
post api_v1_points_path, params: params
|
post api_v1_points_path, params: params
|
||||||
}.to have_enqueued_job(Owntracks::PointCreatingJob)
|
end.to have_enqueued_job(Owntracks::PointCreatingJob)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
60
spec/swagger/api/v1/points_controller_spec.rb
Normal file
60
spec/swagger/api/v1/points_controller_spec.rb
Normal file
|
|
@ -0,0 +1,60 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'swagger_helper'
|
||||||
|
|
||||||
|
describe 'Points API', type: :request do
|
||||||
|
path '/api/v1/points' do
|
||||||
|
post 'Creates a point' do
|
||||||
|
request_body_example value: {
|
||||||
|
lat: 52.502397,
|
||||||
|
lon: 13.356718,
|
||||||
|
tid: 'Swagger',
|
||||||
|
tst: Time.current.to_i
|
||||||
|
}
|
||||||
|
tags 'Points'
|
||||||
|
consumes 'application/json'
|
||||||
|
parameter name: :point, in: :body, schema: {
|
||||||
|
type: :object,
|
||||||
|
properties: {
|
||||||
|
acc: { type: :number },
|
||||||
|
alt: { type: :number },
|
||||||
|
batt: { type: :number },
|
||||||
|
bs: { type: :number },
|
||||||
|
cog: { type: :number },
|
||||||
|
lat: { type: :string, format: :decimal },
|
||||||
|
lon: { type: :string, format: :decimal },
|
||||||
|
rad: { type: :number },
|
||||||
|
t: { type: :string },
|
||||||
|
tid: { type: :string },
|
||||||
|
tst: { type: :number },
|
||||||
|
vac: { type: :number },
|
||||||
|
vel: { type: :number },
|
||||||
|
p: { type: :string, format: :decimal },
|
||||||
|
poi: { type: :string },
|
||||||
|
conn: { type: :string },
|
||||||
|
tag: { type: :string },
|
||||||
|
topic: { type: :string },
|
||||||
|
inregions: { type: :array },
|
||||||
|
SSID: { type: :string },
|
||||||
|
BSSID: { type: :string },
|
||||||
|
created_at: { type: :string },
|
||||||
|
inrids: { type: :array },
|
||||||
|
m: { type: :number }
|
||||||
|
},
|
||||||
|
required: %w[lat lon tid tst]
|
||||||
|
}
|
||||||
|
|
||||||
|
response '200', 'point created' do
|
||||||
|
let(:point) { { lat: 1.0, lon: 2.0, tid: 3, tst: 4 } }
|
||||||
|
|
||||||
|
run_test!
|
||||||
|
end
|
||||||
|
|
||||||
|
response '200', 'invalid request' do
|
||||||
|
let(:point) { { lat: 1.0 } }
|
||||||
|
|
||||||
|
run_test!
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
43
spec/swagger_helper.rb
Normal file
43
spec/swagger_helper.rb
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'rails_helper'
|
||||||
|
|
||||||
|
RSpec.configure do |config|
|
||||||
|
# Specify a root folder where Swagger JSON files are generated
|
||||||
|
# NOTE: If you're using the rswag-api to serve API descriptions, you'll need
|
||||||
|
# to ensure that it's configured to serve Swagger from the same folder
|
||||||
|
config.openapi_root = Rails.root.join('swagger').to_s
|
||||||
|
|
||||||
|
# Define one or more Swagger documents and provide global metadata for each one
|
||||||
|
# When you run the 'rswag:specs:swaggerize' rake task, the complete Swagger will
|
||||||
|
# be generated at the provided relative path under openapi_root
|
||||||
|
# By default, the operations defined in spec files are added to the first
|
||||||
|
# document below. You can override this behavior by adding a openapi_spec tag to the
|
||||||
|
# the root example_group in your specs, e.g. describe '...', openapi_spec: 'v2/swagger.json'
|
||||||
|
config.openapi_specs = {
|
||||||
|
'v1/swagger.yaml' => {
|
||||||
|
openapi: '3.0.1',
|
||||||
|
info: {
|
||||||
|
title: 'API V1',
|
||||||
|
version: 'v1'
|
||||||
|
},
|
||||||
|
paths: {},
|
||||||
|
servers: [
|
||||||
|
{
|
||||||
|
url: 'http://{defaultHost}',
|
||||||
|
variables: {
|
||||||
|
defaultHost: {
|
||||||
|
default: 'localhost:3000'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Specify the format of the output Swagger file when running 'rswag:specs:swaggerize'.
|
||||||
|
# The openapi_specs configuration option has the filename including format in
|
||||||
|
# the key, this may want to be changed to avoid putting yaml in json files.
|
||||||
|
# Defaults to json. Accepts ':json' and ':yaml'.
|
||||||
|
config.openapi_format = :yaml
|
||||||
|
end
|
||||||
90
swagger/v1/swagger.yaml
Normal file
90
swagger/v1/swagger.yaml
Normal file
|
|
@ -0,0 +1,90 @@
|
||||||
|
---
|
||||||
|
openapi: 3.0.1
|
||||||
|
info:
|
||||||
|
title: API V1
|
||||||
|
version: v1
|
||||||
|
paths:
|
||||||
|
"/api/v1/points":
|
||||||
|
post:
|
||||||
|
summary: Creates a point
|
||||||
|
tags:
|
||||||
|
- Points
|
||||||
|
parameters: []
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: invalid request
|
||||||
|
requestBody:
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
acc:
|
||||||
|
type: number
|
||||||
|
alt:
|
||||||
|
type: number
|
||||||
|
batt:
|
||||||
|
type: number
|
||||||
|
bs:
|
||||||
|
type: number
|
||||||
|
cog:
|
||||||
|
type: number
|
||||||
|
lat:
|
||||||
|
type: string
|
||||||
|
format: decimal
|
||||||
|
lon:
|
||||||
|
type: string
|
||||||
|
format: decimal
|
||||||
|
rad:
|
||||||
|
type: number
|
||||||
|
t:
|
||||||
|
type: string
|
||||||
|
tid:
|
||||||
|
type: string
|
||||||
|
tst:
|
||||||
|
type: number
|
||||||
|
vac:
|
||||||
|
type: number
|
||||||
|
vel:
|
||||||
|
type: number
|
||||||
|
p:
|
||||||
|
type: string
|
||||||
|
format: decimal
|
||||||
|
poi:
|
||||||
|
type: string
|
||||||
|
conn:
|
||||||
|
type: string
|
||||||
|
tag:
|
||||||
|
type: string
|
||||||
|
topic:
|
||||||
|
type: string
|
||||||
|
inregions:
|
||||||
|
type: array
|
||||||
|
SSID:
|
||||||
|
type: string
|
||||||
|
BSSID:
|
||||||
|
type: string
|
||||||
|
created_at:
|
||||||
|
type: string
|
||||||
|
inrids:
|
||||||
|
type: array
|
||||||
|
m:
|
||||||
|
type: number
|
||||||
|
required:
|
||||||
|
- lat
|
||||||
|
- lon
|
||||||
|
- tid
|
||||||
|
- tst
|
||||||
|
examples:
|
||||||
|
'0':
|
||||||
|
summary: Creates a point
|
||||||
|
value:
|
||||||
|
lat: 52.502397
|
||||||
|
lon: 13.356718
|
||||||
|
tid: Swagger
|
||||||
|
tst: 1716032145
|
||||||
|
servers:
|
||||||
|
- url: http://{defaultHost}
|
||||||
|
variables:
|
||||||
|
defaultHost:
|
||||||
|
default: localhost:3000
|
||||||
Loading…
Reference in a new issue