How to add multiple examples to a Swagger schema? - swagger

I'm using Swagger with OAS3, since I need anyOf support. I have an API call that can take one of 2 possible schemas, an account or an address. The schema works well in Swagger: it shows, and validates. But the example value shows only the first schema. I created an examples array, per the documentation, but I have no idea where to add it:
const accountSchema = {
description: 'schema for adding a new account',
type: 'object',
properties: {
account: {
type: 'object',
properties: {
userId: {type: 'number'},
platformId: {type: 'number'},
name: {type: 'string'},
key: {type: 'string'},
secret: {type: 'string'},
test: {type: 'boolean'},
},
required: ['userId', 'platformId', 'name', 'key', 'secret']
}
},
};
const ethereumAddressSchema = {
description: 'schema for adding a new ethereum address',
type: 'object',
properties: {
ethereum: {
type: 'object',
properties: {
userId: {type: 'number'},
name: {type: 'string'},
address: {type: 'string'},
chainId: {type: 'number'},
},
required: ['userId','name', 'address']
}
}
};
const examples = [
{
account: {
"userId": 0,
"platformId": 0,
"name": "string",
"key": "string",
"secret": "string",
"test": true
},
},
{
ethereum: {
"userId": 0,
"address": '0xfffffffffffffff',
"name": "string",
"chainId": 1,
}
}
];
const body = {
anyOf: [accountSchema, ethereumAddressSchema]
};
const response = {
type: 'object',
properties: {
accountId: {type: 'number'},
reason: {type: 'string'}
},
required: []
};
const addAccountSchema = {
description: 'Add a new account',
tags: ['account'],
produces: ['application/json'],
summary: 'Add a new account',
body,
response: {
200: {
description: 'Account request valid',
...response
},
404: {
description: 'Account request parameters not found',
...response
},
422: {
description: 'Account request invalid',
...response
}
}
};
module.exports = addAccountSchema;
Where should I add the examples array, or is there a better way to show the user the 2 possible schemas in the UI?

Related

sequelize eager loading for join

Battery.belongsTo(TagType, { constraints: true, onDelete: "CASCADE" });
Tag.belongsTo(TagType, { constraints: true, onDelete: "CASCADE" });
const battery = sequelize.define("Battery", {
id: {
type: Sequelize.INTEGER,
autoIncrement: true,
allowNull: false,
primaryKey: true,
},
voltage: {
type: Sequelize.INTEGER,
allowNull: false,
},
percetange: {
type: Sequelize.INTEGER,
allowNull: false,
},
});
const tag = sequelize.define("Tag", {
id: {
type: Sequelize.INTEGER,
autoIncrement: true,
allowNull: false,
primaryKey: true,
},
name: {
type: Sequelize.STRING,
allowNull: false,
unique: true,
},
battery: {
type: Sequelize.INTEGER,
allowNull: true,
},
});
//api
const percetangeAndTags = [];
const tags = await Tag.findAll({
include: [
{
model: TagType,
attributes: ["name"],
},
],
});
error.catchError("notFound", tags);
await Promise.all(
tags.map(async (tag) => {
const batteryVoltageValue = await Battery.findOne({
where: {
tagTypeId: tag.tagTypeId,
voltage: { [Op.lte]: tag.battery },
},
attributes: [
[Sequelize.fn("max", Sequelize.col("voltage")), "max"],
],
});
const battery = await Battery.findOne({
where: {
tagTypeId: tag.tagTypeId,
voltage: batteryVoltageValue.dataValues.max,
},
});
percetangeAndTags.push({
id: tag.id,
name: tag.name,
tag_type: tag.tag_type.name,
percetange: battery?.percetange,
});
})
);
res.status(200).json(percetangeAndTags);
How can I write this code in the most efficient way?
Because the explanation is short, it doesn't accept the question, so I wrote a poem instead of randomly throwing it.
Keleci bilen kişinin yüzünü ağ ede bir söz
Sözü pişirip diyenin işini sağ ede bir söz
Söz ola kese savaşı söz ola bitire başı
Söz ola ağılı aşı bal ile yağ ede bir söz

OpenAPI 3.0.3 documentation with RSwag Unable to Send "Content-Type" header

For my Rails project I am using RSwag to generate documentation using OpenAPI 3.0.3 specifications.
I know with Open API 3.0.3 'If in is "header" and the name field is "Accept", "Content-Type" or "Authorization", the parameter definition SHALL be ignored.'
However I know they can be generated by configuring the rspec and swagger_helper.rb files properly. For example, my swagger_helper.rb has
config.swagger_docs = {
'v1/swagger.json' => {
openapi: '3.0.3',
info: {
title: 'My company API',
version: 'v1'
},
servers: [
{
url: "#{ENV['PROTOCOL']}://#{ENV['BINDING']}:#{ENV['PORT']}"
}
],
components: {
contentType: 'application/vnd.api+json',
headers: {
contentType: {
description: "content type",
schema: {
type: :string
}
}
},
securitySchemes: {
authorization_header: {
type: :apiKey,
name: 'Authorization',
in: :header,
description: "Expected format: app_name:api_key"
}
},
schemas: {
errors_list: {
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"errors": {
"type": "array",
"items": [
{}
]
}
},
"required": [
"errors"
]
}
}
},
encoding: {
contentType: 'application/vnd.v1+json'
},
mediaType: {
schema: {
type: :string
},
example: 'application/vnd.v1+json',
encoding: {
contentType: 'application/vnd.v1+json'
}
}
}
}
and one of my rspec file has
path '/api/segments/{id}', swagger_doc: 'v1/swagger.json' do
get 'Show segment by id' do
after do |example|
example.metadata[:response][:content] = { 'application/json' => JSON.parse(response.body, symbolize_names: true) }
end
let(:segment) { create(:segment, user: user) }
let(:id) { segment.id }
let(:Authorization) { auth_header }
produces 'application/vnd.my_company.v1+json'
consumes 'application/vnd.api+json'
security [ authorization_header: [] ]
tags :segments
parameter name: :Accept, in: :header, type: :string, required: true, example: 'application/vnd.my_company.v1+json'
parameter name: 'Content-Type', in: :header, type: :string, required: true, example: 'application/vnd.api+json'
parameter name: :Authorization, in: :header, type: :string, required: true
parameter name: :id, in: :path, type: :integer , required: true, description: 'id of segment'
parameter name: :marketplace, in: :query, type: :string, schema: { type: :string }, required: true, description: 'marketplace of segment'
context 'abc' do
response '200', :success do
run_test! do |response|
xxxx
end
end
end
end
With the definitions for securitySchemes and using it with security [ authorization_header: [] ], as well as using produces 'application/vnd.my_company.v1+json', I am able to send Authorization and Accept headers on my swagger UI page using the "Try it out" functionality.
However, I am not able to send the Content-Type header. Where did I do wrong?
I know if I use Swagger 2.0 instead of OpenAPI 3.0.3 this problem will not occur, but I don't want to switch.
Update:
I manually added:
"requestBody": {
"content": {
"application/vnd.api+json": {}
}
},
underneath
"paths": {
"/api/segments/{id}": {
"get": {
"summary": "Show segment by id",
"security": [
{
"authorization_header": [
]
}
],
"tags": [
"segments"
],
"requestBody": {
"content": {
"application/vnd.api+json": {}
}
},
in my swagger.json file and now it lets me send Content-Type header!
But how do I do it in my swagger_helper.rb or the rspec file?
Thank you!

Typeorm many-to-one / one-to-many resulting in unexpected results

I am new to Typeorm but I feel like I have a fairly simple example that is resulting in some unexpected results. Lets say I have a Client. Each Client can have many ClientUsers. Each ClientUser can have only one Client.
Example:
Client Schema:
module.exports = new EntitySchema({
name: "Client",
target: Client,
columns: {
id: {
primary: true,
type: "uuid",
generated: "uuid"
},
name: {
type: "varchar"
},
telephone: {
type: "varchar"
},
email: {
type: "varchar"
}
},
relations: {
client_users: {
target: "ClientUser",
type: "one-to-many",
cascade: true
}
}
});
ClientUser Schema:
module.exports = new EntitySchema({
name: "ClientUser",
target: ClientUser,
columns: {
id: {
primary: true,
type: "uuid",
generated: "uuid"
},
first_name: {
type: "varchar"
},
last_name: {
type: "varchar"
},
title: {
type: "varchar"
},
email: {
type: "varchar"
},
username: {
type: "varchar"
},
password: {
type: "varchar"
}
},
relations: {
client: {
target: "Client",
type: "many-to-one",
joinColumn: true,
cascade: true
}
}
});
This result in the ClientUser table having a column called clientid, which is always null. If I change ClientUser schema relation to the following (update client to client_id):
relations: {
client_id: {
target: "Client",
type: "many-to-one",
joinColumn: true,
cascade: true
}
}
I get a column named clientIdId but the column is correctly populated with the related client id.
I am obviously doing something really simply wrong here but I've been looking at it so long, it escapes me. Please help me understand how I can have a logical column name, that gets populated as expected.

TypeORM does not save relations

I have the following entity which I want to save:
#Entity('approvals')
export class Approval {
#PrimaryGeneratedColumn()
id: string;
#ManyToOne(type => Task, task => task.approvals, {nullable: false, onDelete: 'CASCADE', lazy: true})
task: Promise<Task> | Task;
#ManyToOne(type => User, user => user.approvals, {nullable: false, onDelete: 'CASCADE', lazy: true})
user: Promise<User> | User;
#Column({ type: 'enum', enum: ApprovalState, default: ApprovalState.None })
state: ApprovalState;
constructor(partialApproval: Partial<Approval>) {
Object.assign(this, partialApproval);
}
}
If I want to save an entity which looks like (copied while debugging):
[
{
"task": {
"id": "2",
"name": "task1",
"type": "type1",
"neededTimeSeconds": 0,
"factor": 1,
"userId": "1",
"periodStart": "2019-01-01",
"periodEnd": "2019-01-31",
"done": true,
"__user__": {
"id": "1",
"username": "user1",
"password": "$2b$10$SBPIVm9p8L4YkpiUVJ.mpedIgWi5Je6MuWTM7IvgMdyhr27JYM0OG",
"credits": 0,
"gravatarHash": null
},
"__has_user__": true
},
"user": {
"id": "2",
"username": "shouldHaveApprovalUser1",
"password": "password1",
"credits": 0,
"gravatarHash": null
}
},
{
"task": {
"id": "2",
"name": "task1",
"type": "type1",
"neededTimeSeconds": 0,
"factor": 1,
"userId": "1",
"periodStart": "2019-01-01",
"periodEnd": "2019-01-31",
"done": true,
"__user__": {
"id": "1",
"username": "user1",
"password": "$2b$10$SBPIVm9p8L4YkpiUVJ.mpedIgWi5Je6MuWTM7IvgMdyhr27JYM0OG",
"credits": 0,
"gravatarHash": null
},
"__has_user__": true
},
"user": {
"id": "3",
"username": "shouldHaveApprovalUser2",
"password": "password1",
"credits": 0,
"gravatarHash": null
}
}
]
Then calling repository.save() with the above array, I get:
null value in column "taskId" violates not-null constraint
Although there is clearly the id defined in each task.
This is the Task entity class:
#Entity('tasks')
export class Task {
#PrimaryGeneratedColumn({ type: 'bigint' })
id: string;
#Column({ length: 30 })
name: string;
#Column({ default: 'help' })
type: string;
#Column({ name: 'needed_time', type: 'int', nullable: true })
neededTimeSeconds: number;
#Column({ type: 'int', default: 1 })
factor: number;
#ManyToOne(type => User, { nullable: true, lazy: true })
#JoinColumn({ name: 'user_id' })
user: Promise<User>;
#Column({ name: 'user_id' })
#RelationId((task: Task) => task.user)
userId: string;
#Column({ name: 'period_start', type: 'date', default: new Date() })
periodStart: string;
#Column({ name: 'period_end', type: 'date', default: new Date() })
periodEnd: string;
#Column({ type: 'boolean', default: false })
done: boolean;
#OneToMany(type => Approval, approval => approval.task, { nullable: true, lazy: true })
approvals: Promise<Approval[]>;
#OneToMany(type => TaskMessage, taskMessage => taskMessage.task, { cascade: ['remove'], lazy: true })
messages: Promise<TaskMessage[]>;
constructor(partialTask: Partial<Task>) {
Object.assign(this, partialTask);
}
}
Can anyone tell me why the relation task is not going to be assigned/saved?
I think you are missing cascade: true for the options of the relations, this should be set on the loose side of the relation (OneToMany) - check the example
You can use Typeorm's cascades for this: https://orkhan.gitbook.io/typeorm/docs/relations#cascades
Setting the cascade property in your relationship decorator changes the behavior of typeorm's .save() method.
#OneToMany(type => Approval, approval => approval.task, {
nullable: true,
lazy: true,
cascade: ["insert", "update", "remove"]
})
approvals: Approval[];
With cascades enabled, you can insert, update or remove related entities with a single call to .save().
To create a new approval and insert task:
await this.approvalsEntity.save({ ...approvalData, task: taskData })
To update a task on a pre-existing approval:
await this.approvalsEntity.save({
id: approvalId,
task: { id: taskId, ...approvalUpdate }
})

Extjs 5.1.1 does not work on server production

I'm developing an application with MVC Asp.NET 5 Extjs 5.1.1. In development environment it works fine.
I have the next problem:
my extjs model:
Ext.define('Wts.model.DailyRegister', {
extend: 'Ext.data.Model',
fields: [
{
name: 'Year',
type: 'int',
mapping: 'DailyRegister.Year'
},
{
name: 'Month',
type: 'int',
mapping: 'DailyRegister.Month'
},
{
name: 'Project_ID',
type: 'int',
mapping: 'DailyRegister.Project_ID'
},
{
name: 'Project_Name',
type: 'string'
},
{
name: 'Activity_ID',
type: 'int',
mapping: 'DailyRegister.Activity_ID'
},
{
name: 'Activity_Name',
type: 'string'
},
{
name: 'Activity_UnitCost',
type: 'number'
},
{
name: 'Date',
type: 'date',
dateFormat: 'MS'
},
{
name: 'ActivityType',
type: 'int'
},
{
name: 'Employee_ID',
type: 'int',
mapping: 'DailyRegister.Employee_ID'
},
{
name: 'Day',
type: 'int',
mapping: 'DailyRegister.Day'
},
{
name: 'WorkedHours',
type: 'number',
mapping: 'DailyRegister.WorkedHours',
convert: function(value, record) {
if (record.get('ActivityType') == 1) {
return window.convertNumberToTime(value);
}
return value;
},
serialize: function(value, record) { /
if (record.get('ActivityType') == 1) {
return window.convertTimeToNumber(value);
}
return value;
}
},
{
name: 'Sum',
type: 'number',
mapping: 'DailyRegister.Sum'
},
{
name: 'Comments',
type: 'string',
mapping: 'DailyRegister.Comments',
},
{
name: 'ItWasSended',
type: 'boolean',
mapping: 'DailyRegister.ItWasSended',
},
{
name: 'DataRange',
type: 'bool'
},
{
name: 'EndDate',
type: 'date',
dateFormat: 'MS'
}
]
});
When I try to create a DailyRegister on development environment
When I try to create a DailyRegister on production environment, field WorkedHours is not sent Any idea?
Suggestions:
Ddebug under testing code. Plz use "sencha app build testing" to build the testing package.
Remove one of the "convert"/"serialise" config to see whether your http params contain the "WorkedHours" param.

Resources