Array of Multiple items in Swagger - node.js

So I'm creating a user endpoint with nodejs to add a user to the database , and for the api documentation I'm using swagger editor and I'm completely new to it.
what I want to do is add a user with login , password , avatar but that user has multiple roles I want to add to the database
what I have done in the yaml document in the swagger editor is this
/users/add:
post:
description: ''
operationId: AddUser
parameters:
- description: The user login
in: formData
name: user
required: true
type: string
- description: The user password
in: formData
name: password
required: true
type: string
- description: The user name
in: formData
name: username
required: true
type: string
- description: The user avatar
in: formData
name: avatar
required: true
type: file
- in: formData
name: roles
description: roles
required: false
type: array
items:
type: string
collectionFormat: multi
and it's kind of displaying what I want in the swagger editor
but what i'm getting in the UI is just an input field
In conclusion what I want to get is an inputted array which contains the user roles and input them in the database.
Thank you

What version of Swagger UI are you using? I am on version 2.1.1 and when I put the same definition as you I get the following input box for an array field.
Try upgrading to the newest version of Swagger UI.
Also, if you update the "in" field to be "query" the resulting URL will look like this:
http://localhost:8080/accounts?roles=admin%2Cguest%2Cuser
You can then access the array values in the URL parameters rather than in "formData".

Related

Add multiple object examples for multipart/form-data in Swagger docs

I hava a POST API using multipart/form-data to send data (requestBody including a binary file, string and object data).
I want to add more than one example for object parameter, but I found using enum is not working:
here is my swagger docs:
post:
tags:
- user
summary: xxx
description: xxx
requestBody:
content:
multipart/form-data:
schema:
$ref: '#/components/schemas/User4'
User4:
type: object
properties:
thisIsAString:
type: string
default: 'testStr'
enum:
- testStr
- testStr2
thisIsAObj:
type: object
default: obj1
enum:
- obj1:
oneOfEx: 'bbb'
- obj2:
oneOfEx2: 'aaa'
file:
type: string
format: binary
What I want is make the eample of thisIsAObj parameter can be changed by a Drop-down list.
Or can I separate the binary file and object data like this?
Thank you.

How to design a schema model for different users

I'm new to mongodb and I'm working on my personal project which is a project management system for college projects. I have 3 users admin(the department), students, and advisor. The admin is the one who registers both the students and the advisors. All the users have some common fields like name, email, and password. And different fields of there own.
Their roles:-
- Admin -> adds the students and advisors
- Student -> choose projects and work on the projects in a team
- Advisor -> advice students based on their progress on their project
My problem is in designing the model should I use one userSchema and add all the users in one collection or create different collections for each user.
My second confusion is if I create different collections for each user how can I deal with authentication and authorization? I'm using node js for the backend.
Can I get some guidance and suggestion?
It's your choice.
Here, I would suggest to use a single Collection for all the 3 types of Users.
Since everyone would be having same functionalities like name, email, password etc. on registration, single Schema would work for sure.
So create on schema of suppose 'User' and then use one 'tag' selector to identify the admin, advisor and student.
I would do something like this:
var userSchema = new mongoose.Schema({
email: {
type: String,
unique: true,
required: true,
},
name: {
type: String,
required: true,
},
tag : {
type: String
},
Addtasks: [
{
topic: String,
words: Number,
keywords: String,
website: String,
otherdetails: String,
exampleRadios: String,
deadline: Date,
Date: String,
fileName: String
},
],
});
module.exports = mongoose.model('User', userSchema);
With this create one page for authentication as auth.js separately and write the single authentication code there using passport module authentication. With that said now you can use one authentication validation for all 3 dashboards.
For handlebars as front-end use this to check the user if he/she has logged in or not.
{{if #user}}
<html>
<head>
.
.
.
...
following this you can achieve this.

OpenAPI: Mandatory properties of an Optional Property

Pretty much what the title says. I have an optional object in the request body. However, if that object is given, it should mandatorily contain a few child properties.
My OpenAPI component config looks like this:
UserDetails:
type: object
properties:
surname:
type: string
givenName:
type: string
dob:
type: string
format: date
gender:
type: string
enum:
- male
- female
- others
partner:
type: object
properties:
name:
type: string
phone:
type: string
maxLength: 10
minLength: 10
pattern: ^[1-9]+[0-9]{9}$
required: [name, phone]
required:
- surname
- givenName
- dob
I am using express-openapi-validator to validate this. Now, I don't understand if this is the problem of the express-openapi-validator package or not, but the required fields (name, phone) of the optional field (partner) is never validated. I can just provide partner: {} and it slips in right through, or even, partner: { name: 'some name', phone: '123' }. Phone number should be validated for the length and the regex.
Am I missing anything in the definition?
There does not seem to be a solution to this, but I am closing this just for peace to my mind.
like what #Helen has replied, this seems to be an issue with the library itself.
In the process of developing my application, I discovered more problems, which make the the library express-openapi-validator and another library swagger-express-middleware I used, even lesser reliable for validating requests.
The other problem that I discovered was that a value is validated with a provided enum only if it is provided as an array:
eg. The following is validated correctly:
UserLiabilities:
type: object
properties:
liabilities:
type: object
properties:
creditCards:
type: array
items:
allOf:
- $ref: '#/components/schemas/Provider'
- type: object
properties:
limit:
type: number
minimum: 0
Here Provider is:
Provider:
type: object
properties:
provider:
type: string
enum: ['ABC', 'DEF', 'GHI', 'Others']
However, if I need provider as a plain string in an object (not in an array like above), it is not validated. And, it allows any arbitrary string:
homeLoan:
allOf:
- $ref: '#/components/schemas/Provider'
- type: object
properties:
amount:
type: number
minimum: 0
This behavior is consistent with atleast two libraries that I have tried and mentioned above. I am not sure I am doing something wrong here, but I have lost enough time trying to debug this and had to finally resolve this in my server itself.

How to handle non-required parameters in Swagger to avoid missing positional argument error?

I have a Swagger file for my endpoints, one of my endpoints has several parameters. How do you handle non-required parameters? I'm having a challenge on how to handle it on my Python file if the non-required parameters have empty value.
Here is my Swagger definition:
/surveyData:
get:
operationId: "surveyData.read_surveydata"
summary: Gets the survey data for the client insights tracker.
parameters:
- in: query
name: startDate
type: string
required: true
description: The start date of the survey data.
- in: query
name: endDate
type: string
required: true
description: The end date of the survey data.
- in: query
name: country
type: string
description: The countries from which you would like to filter the survey data.
- in: query
name: market
type: string
and here is my function which is written in Python (using Connexion):
def read_surveydata(startDate, endDate, country, market):
You can add the "Default" tag for example:
parameters:
- name: filtros
in: "query"
required: false
description: Filter to query
type: "string"
default: "bndu"
Or add a default argument
def read_surveydata(startDate, endDate, country, market='store'):

How can I 'resolve' a MogoDB object to a specific JSON structure in Nodejs?

Suppose the following User Schema in MongoDB (using Mongoose/Nodejs):
var UserSchema = new Schema({
email: {
type: String,
unique: true,
required: 'User email is required.'
},
password: {
type: String,
required: 'User password is required.'
},
token: {
type: String,
unique: true,
default: hat
},
created_at: {
type: Date,
default: Date.now
},
});
// mongoose-encrypt package
UserSchema.plugin(encrypt, {
secret: 'my secret',
encryptedFields: ['email', 'password', 'token', 'created_at']
});
Now assume I want to return the user object from an API endpoint. In fact, suppose I want to return user objects from multiple API endpoints. Possibly as a standalone object, possibly as a related model.
Obviously, I don't want password to be present in the returned structure - and in many cases I wouldn't want token to be returned either. I could do this manually on every endpoint, but I'd prefer a no-thought solution - being able to simply retrieve the user, end of story, and not worry about unsetting certain values after the fact.
I mainly come from the world of Laravel, where things like API Resources (https://laravel.com/docs/5.6/eloquent-resources) exist. I already tried implementing the mongoose-hidden package (https://www.npmjs.com/package/mongoose-hidden) to hide the password and token, but unfortunately it seems as though that breaks the encryption package I'm using.
I'm new to Nodejs and MongoDB in general - is there a good way to implement this?
How to protect the password field in Mongoose/MongoDB so it won't return in a query when I populate collections?
You can use this: Users.find().select("-password"),
but this is done whenever you send the queried item to the user (res.json()...) so you can do your manipultions with this field included and then remove it from the user before you send it back (this is using the promise approach, the best practice).
And if you want your changes to be used as default you can add "select: false" into the schema object's password field.
Hope this helps :)

Resources