Chore: Swagger Docs V1 (#546)

This commit is contained in:
Sony Mathew 2020-02-23 12:54:29 +05:30 committed by GitHub
parent eea92bd0ac
commit e2688d5176
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
25 changed files with 739 additions and 0 deletions

4
.gitignore vendored
View file

@ -37,6 +37,10 @@ public/packs*
*.swo
*.un~
.jest-cache
#VS Code files
.vscode
# ignore jetbrains IDE files
.idea

View file

@ -83,6 +83,9 @@ group :development do
gem 'bullet'
gem 'letter_opener'
gem 'web-console'
# used in swagger build
gem 'json_refs', git: 'https://github.com/sony-mathew/json_refs', ref: 'b6c142a'
end
group :development, :test do

View file

@ -5,6 +5,14 @@ GIT
twitty (0.1.0)
oauth
GIT
remote: https://github.com/sony-mathew/json_refs
revision: b6c142ae486e399d00fbc758e21a7ed63a934f61
ref: b6c142a
specs:
json_refs (0.1.2)
hana
GEM
remote: https://rubygems.org/
specs:
@ -201,6 +209,7 @@ GEM
os (>= 0.9, < 2.0)
signet (~> 0.12)
haikunator (1.1.0)
hana (1.3.5)
hashie (4.1.0)
http-accept (1.7.0)
http-cookie (1.0.3)
@ -498,6 +507,7 @@ DEPENDENCIES
haikunator
hashie
jbuilder
json_refs!
jwt
kaminari
koala

View file

@ -0,0 +1,18 @@
class SwaggerController < ApplicationController
def respond
if Rails.env.development? || Rails.env.test?
render inline: File.read(Rails.root.join('swagger', derived_path))
else
head 404
end
end
private
def derived_path
params[:path] ||= 'index.html'
path = params[:path]
path << ".#{params[:format]}" unless path.ends_with?(params[:format].to_s)
path
end
end

View file

@ -144,4 +144,8 @@ Rails.application.routes.draw do
mount Sidekiq::Web, at: '/sidekiq'
end
# ----------------------------------------------------------------------
# Routes for swagger docs
get '/swagger/*path', to: 'swagger#respond'
get '/swagger', to: 'swagger#respond'
end

22
lib/tasks/swagger.rake Normal file
View file

@ -0,0 +1,22 @@
namespace :swagger do
desc 'build combined swagger.json file from all the fragmented definitions and paths inside swagger folder'
task build: :environment do
require 'json_refs'
base_path = Rails.root.join('swagger')
Dir.chdir(base_path) do
swagger_index = YAML.safe_load(File.open('index.yml'))
final_build = JsonRefs.call(
swagger_index,
resolve_local_ref: false,
resolve_file_ref: true,
logging: true
)
File.write('swagger.json', JSON.pretty_generate(final_build))
puts 'Swagger build was succesful.'
puts "Generated #{base_path}/swagger.json"
puts 'Go to http://localhost:3000/swagger see the changes.'
end
end
end

View file

@ -0,0 +1,12 @@
require 'rails_helper'
describe '/swagger', type: :request do
describe 'GET /swagger' do
it 'renders swagger index.html' do
get '/swagger'
expect(response).to have_http_status(:success)
expect(response.body).to include('redoc')
expect(response.body).to include('/swagger.json')
end
end
end

View file

@ -0,0 +1,9 @@
title: data
type: object
properties:
description:
type: string
errors:
type: array
items:
$ref: '#/definitions/request_error'

View file

@ -0,0 +1,8 @@
type: object
properties:
field:
type: string
message:
type: string
code:
type: string

View file

@ -0,0 +1,39 @@
# ERROR
bad_request_error:
$ref: ./error/bad_request.yml
request_error:
$ref: ./error/request.yml
# RESOURCE
contact:
$ref: ./resource/contact.yml
conversation:
$ref: ./resource/conversation.yml
# RESPONSE
extended_contact:
allOf:
- $ref: '#/definitions/contact'
- $ref: ./resource/extension/contact/show.yml
contact_base:
allOf:
- $ref: '#/definitions/contact'
- $ref: ./resource/extension/generic.yml
contact_list:
type: array
items:
allOf:
- $ref: '#/definitions/contact'
- $ref: ./resource/extension/generic.yml
contact_conversations:
type: array
items:
allOf:
- $ref: '#/definitions/conversation'
- $ref: ./resource/extension/contact/conversation.yml
# REQUEST
contact_create:
$ref: ./request/contact/create.yml
contact_update:
$ref: ./request/contact/update.yml

View file

@ -0,0 +1,6 @@
type: object
properties:
account_id:
type: number
inbox_id:
type: number

View file

@ -0,0 +1,8 @@
type: object
properties:
name:
type: string
email:
type: string
phone_number:
type: string

View file

@ -0,0 +1,12 @@
type: object
properties:
email:
type: string
name:
type: string
phone_number:
type: string
thumbnail:
type: string
additional_attributes:
type: object

View file

@ -0,0 +1,21 @@
type: object
properties:
display_id:
type: number
messages:
type: array
items:
type: object
inbox_id:
type: number
status:
type: string
enum: ['open', 'resolved']
timestamp:
type: string
user_last_seen_at:
type: string
agent_last_seen_at:
type: agent_last_seen_at
unread_count:
type: number

View file

@ -0,0 +1,18 @@
type: object
properties:
meta:
type: object
properties:
sender:
type: object
properties:
id:
type: number
name:
type: string
thumbnail:
type: string
channel:
type: string
assignee:
type: object

View file

@ -0,0 +1,5 @@
type: object
properties:
allOf:
- $ref: '#/definitions/contact'
- $ref: ./resource/extension/contact.yaml

View file

@ -0,0 +1,7 @@
type: object
properties:
id:
type: number
availability_status:
type: string
enum: ['online', 'offline']

View file

@ -0,0 +1,4 @@
type: object
properties:
id:
type: number

23
swagger/index.html Normal file
View file

@ -0,0 +1,23 @@
<!DOCTYPE html>
<html>
<head>
<title>ReDoc</title>
<!-- needed for adaptive design -->
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://fonts.googleapis.com/css?family=Montserrat:300,400,700|Roboto:300,400,700" rel="stylesheet">
<!--
ReDoc doesn't change outer page styles
-->
<style>
body {
margin: 0;
padding: 0;
}
</style>
</head>
<body>
<redoc spec-url='/swagger/swagger.json'></redoc>
<script src="https://cdn.jsdelivr.net/npm/redoc@next/bundles/redoc.standalone.js"> </script>
</body>
</html>

17
swagger/index.yml Normal file
View file

@ -0,0 +1,17 @@
swagger: 2.0
info:
description: This is the api documentation for Chatwoot server.
version: 1.0.0
title: Chatwoot
termsOfService: https://www.chatwoot.com/terms-of-service/
contact:
email: support@chatwoot.com
license:
name: MIT License
url: https://opensource.org/licenses/MIT
host: app.chatwoot.com
basePath: /api/v1/
paths:
$ref: ./paths/index.yml
definitions:
$ref: ./definitions/index.yml

View file

@ -0,0 +1,18 @@
get:
tags: [Contact]
summary: Conversations
parameters:
- name: id
in: path
type: number
description: ID of contact
required: true
responses:
200:
description: Success
schema:
$ref: '#/definitions/contact_conversations'
404:
description: Contact not found
403:
description: Access denied

View file

@ -0,0 +1,42 @@
get:
tags: [Contact]
summary: Show Contact
parameters:
- name: id
in: path
type: number
description: ID of contact
required: true
responses:
200:
description: Success
schema:
$ref: '#/definitions/extended_contact'
404:
description: Contact not found
403:
description: Access denied
put:
tags: [Contact]
summary: Update Contact
parameters:
- name: id
in: path
type: number
description: ID of the contact
required: true
- name: data
in: body
required: true
schema:
$ref: '#/definitions/contact_update'
responses:
204:
description: Success
schema:
$ref: '#/definitions/contact_base'
404:
description: Contact not found
403:
description: Access denied

View file

@ -0,0 +1,36 @@
get:
tags: [Contact]
description: Listing all contacts with pagination
summary: List contacts
parameters:
- name: query_hash
in: query
type: string
responses:
200:
description: Success
schema:
$ref: '#/definitions/contact_list'
400:
description: Bad Request Error
schema:
$ref: '#/definitions/bad_request_error'
post:
tags: [Contact]
description: Create a contact
parameters:
- name: data
in: body
required: true
schema:
$ref: '#/definitions/contact_create'
responses:
200:
description: Success
schema:
$ref: '#/definitions/extended_contact'
400:
description: Bad Request Error
schema:
$ref: '#/definitions/bad_request_error'

7
swagger/paths/index.yml Normal file
View file

@ -0,0 +1,7 @@
# Contacts
/contacts:
$ref: ./contact/list_create.yml
/contacts/{id}:
$ref: ./contact/crud.yml
/contacts/{id}/conversations:
$ref: ./contact/conversations.yml

386
swagger/swagger.json Normal file
View file

@ -0,0 +1,386 @@
{
"swagger": 2.0,
"info": {
"description": "This is the api documentation for Chatwoot server.",
"version": "1.0.0",
"title": "Chatwoot",
"termsOfService": "https://www.chatwoot.com/terms-of-service/",
"contact": {
"email": "support@chatwoot.com"
},
"license": {
"name": "MIT License",
"url": "https://opensource.org/licenses/MIT"
},
"host": "app.chatwoot.com",
"basePath": "/api/v1/"
},
"paths": {
"/contacts": {
"get": {
"tags": [
"Contact"
],
"description": "Listing all contacts with pagination",
"summary": "List contacts",
"parameters": [
{
"name": "query_hash",
"in": "query",
"type": "string"
}
],
"responses": {
"200": {
"description": "Success",
"schema": {
"$ref": "#/definitions/contact_list"
}
},
"400": {
"description": "Bad Request Error",
"schema": {
"$ref": "#/definitions/bad_request_error"
}
}
}
},
"post": {
"tags": [
"Contact"
],
"description": "Create a contact",
"parameters": [
{
"name": "data",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/contact_create"
}
}
],
"responses": {
"200": {
"description": "Success",
"schema": {
"$ref": "#/definitions/extended_contact"
}
},
"400": {
"description": "Bad Request Error",
"schema": {
"$ref": "#/definitions/bad_request_error"
}
}
}
}
},
"/contacts/{id}": {
"get": {
"tags": [
"Contact"
],
"summary": "Show Contact",
"parameters": [
{
"name": "id",
"in": "path",
"type": "number",
"description": "ID of contact",
"required": true
}
],
"responses": {
"200": {
"description": "Success",
"schema": {
"$ref": "#/definitions/extended_contact"
}
},
"404": {
"description": "Contact not found"
},
"403": {
"description": "Access denied"
}
}
},
"put": {
"tags": [
"Contact"
],
"summary": "Update Contact",
"parameters": [
{
"name": "id",
"in": "path",
"type": "number",
"description": "ID of the contact",
"required": true
},
{
"name": "data",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/contact_update"
}
}
],
"responses": {
"204": {
"description": "Success",
"schema": {
"$ref": "#/definitions/contact_base"
}
},
"404": {
"description": "Contact not found"
},
"403": {
"description": "Access denied"
}
}
}
},
"/contacts/{id}/conversations": {
"get": {
"tags": [
"Contact"
],
"summary": "Conversations",
"parameters": [
{
"name": "id",
"in": "path",
"type": "number",
"description": "ID of contact",
"required": true
}
],
"responses": {
"200": {
"description": "Success",
"schema": {
"$ref": "#/definitions/contact_conversations"
}
},
"404": {
"description": "Contact not found"
},
"403": {
"description": "Access denied"
}
}
}
}
},
"definitions": {
"bad_request_error": {
"title": "data",
"type": "object",
"properties": {
"description": {
"type": "string"
},
"errors": {
"type": "array",
"items": {
"$ref": "#/definitions/request_error"
}
}
}
},
"request_error": {
"type": "object",
"properties": {
"field": {
"type": "string"
},
"message": {
"type": "string"
},
"code": {
"type": "string"
}
}
},
"contact": {
"type": "object",
"properties": {
"email": {
"type": "string"
},
"name": {
"type": "string"
},
"phone_number": {
"type": "string"
},
"thumbnail": {
"type": "string"
},
"additional_attributes": {
"type": "object"
}
}
},
"conversation": {
"type": "object",
"properties": {
"display_id": {
"type": "number"
},
"messages": {
"type": "array",
"items": {
"type": "object"
}
},
"inbox_id": {
"type": "number"
},
"status": {
"type": "string",
"enum": [
"open",
"resolved"
]
},
"timestamp": {
"type": "string"
},
"user_last_seen_at": {
"type": "string"
},
"agent_last_seen_at": {
"type": "agent_last_seen_at"
},
"unread_count": {
"type": "number"
}
}
},
"extended_contact": {
"allOf": [
{
"$ref": "#/definitions/contact"
},
{
"type": "object",
"properties": {
"id": {
"type": "number"
},
"availability_status": {
"type": "string",
"enum": [
"online",
"offline"
]
}
}
}
]
},
"contact_base": {
"allOf": [
{
"$ref": "#/definitions/contact"
},
{
"type": "object",
"properties": {
"id": {
"type": "number"
}
}
}
]
},
"contact_list": {
"type": "array",
"items": {
"allOf": [
{
"$ref": "#/definitions/contact"
},
{
"type": "object",
"properties": {
"id": {
"type": "number"
}
}
}
]
}
},
"contact_conversations": {
"type": "array",
"items": {
"allOf": [
{
"$ref": "#/definitions/conversation"
},
{
"type": "object",
"properties": {
"meta": {
"type": "object",
"properties": {
"sender": {
"type": "object",
"properties": {
"id": {
"type": "number"
},
"name": {
"type": "string"
},
"thumbnail": {
"type": "string"
},
"channel": {
"type": "string"
}
}
},
"assignee": {
"type": "object"
}
}
}
}
}
]
}
},
"contact_create": {
"type": "object",
"properties": {
"account_id": {
"type": "number"
},
"inbox_id": {
"type": "number"
}
}
},
"contact_update": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"email": {
"type": "string"
},
"phone_number": {
"type": "string"
}
}
}
}
}