Quellcode durchsuchen

Improved swagger design and extensibility

pull/58/head
dusan.lazarevic vor 3 Jahren
Ursprung
Commit
47e9e143df

+ 7
- 0
src/documentation/basicInfo.js Datei anzeigen

@@ -0,0 +1,7 @@
module.exports = {
openapi: "3.0.3",
info: {
title: "Trampa",
description: "Trampa api"
}
}

+ 41
- 0
src/documentation/components.js Datei anzeigen

@@ -0,0 +1,41 @@
module.exports = {
components: {
schemas: {
id: {
type: "string",
description: "An id of a user"
},
User: {
type: "object",
properties: {
name: {
type: "string"
},
email: {
type: "string"
},
password: {
type: "string"
},
tokens: {
type: "array",
items: {
type: "string"
}
}
}
},
Token: {
type: "object",
properties: {
token: {
type: "string"
},
userId: {
type: "string"
}
}
}
}
}
}

+ 14
- 0
src/documentation/index.js Datei anzeigen

@@ -0,0 +1,14 @@
const basicInfo = require('./basicInfo');
const servers = require('./servers');
const components = require('./components');
const tags = require('./tags');
const routesDesc = require('./routesDesc');
module.exports = {
...basicInfo,
...servers,
...components,
...tags,
...routesDesc
}

+ 34
- 0
src/documentation/routesDesc/index.js Datei anzeigen

@@ -0,0 +1,34 @@
const getUser = require('./user/getUserDesc');
const getUsers = require('./user/getUsersDesc');
const createUser = require('./user/createUserDesc');
const updateUser = require('./user/updateUserDesc');
const updateUserContacts = require('./user/updateUserContactsDesc');
const deleteUserDesc = require('./user/deleteUserDesc');
const loginUserDesc = require('./token/loginUserDesc');
const logoutDesc = require('./token/logoutDesc');
const refreshTokenDesc = require('./token/refreshTokenDesc');
module.exports = {
paths: {
'/users': {
...getUsers,
...createUser
},
'/users/{id}': {
...getUser,
...updateUser,
...updateUserContacts,
...deleteUserDesc
},
'/auth/token': {
...loginUserDesc
},
'/auth/logout': {
...logoutDesc
},
'/auth/refresh': {
...refreshTokenDesc
}
}
}

+ 35
- 0
src/documentation/routesDesc/token/loginUserDesc.js Datei anzeigen

@@ -0,0 +1,35 @@
module.exports = {
post: {
tags: ["Token"],
description: "Log in user",
parameters: [],
requestBody: {
content: {
"application/json": {
schema: {
type: "object",
properties: {
email: {
type: "string"
},
password: {
type: "string"
}
}
}
}
}
},
responses: {
201: {
description: "User logged in successfully!"
},
400: {
description: "Wrong credentials!"
},
500: {
description: "Internal server error"
}
}
}
}

+ 27
- 0
src/documentation/routesDesc/token/logoutDesc.js Datei anzeigen

@@ -0,0 +1,27 @@
module.exports = {
post: {
tags: ["Token"],
description: "Log out user",
parameters: [],
requestBody: {
content: {
"application/json": {
schema: {
$ref: "#/components/schemas/Token"
}
}
}
},
responses: {
201: {
description: "User logged out successfully"
},
404: {
description: "No user has the token provided!"
},
500: {
description: "Internal server error"
}
}
}
}

+ 24
- 0
src/documentation/routesDesc/token/refreshTokenDesc.js Datei anzeigen

@@ -0,0 +1,24 @@
module.exports = {
post: {
tags: ["Token"],
description: "Log out user",
parameters: [],
requestBody: {
content: {
"application/json": {
schema: {
$ref: "#/components/schemas/Token"
}
}
}
},
responses: {
201: {
description: "User refreshed successfully"
},
404: {
description: "Token not valid!"
}
}
}
}

+ 48
- 0
src/documentation/routesDesc/user/createUserDesc.js Datei anzeigen

@@ -0,0 +1,48 @@
module.exports = {
post: {
tags: ["User"],
description: "Create user",
parameters: [],
requestBody: {
content: {
"application/json": {
schema: {
type: "object",
properties: {
name: {
type: "string"
},
email: {
type: "string"
},
password: {
type: "string"
}
}
}
}
}
},
responses: {
201: {
description: "User created successfully",
content: {
"application/json": {
schema: {
$ref: "#/components/schemas/User"
},
},
},
},
400: {
description: "Object cant be empty",
},
401: {
description: "Invalid input parameters",
},
500: {
description: "Internal server error",
}
}
}
}

+ 30
- 0
src/documentation/routesDesc/user/deleteUserDesc.js Datei anzeigen

@@ -0,0 +1,30 @@
module.exports = {
delete: {
tags: ["User"],
description: "Delete user",
parameters: [
{
name: "id",
in: "path",
schema: {
$ref: "#/components/schemas/id",
},
required: true,
},
],
responses: {
204: {
description: "User deleted successfully",
},
400: {
description: "You need to provide valid Id'",
},
404: {
description: "User not found",
},
500: {
description: "Internal server error",
},
},
},
};

+ 38
- 0
src/documentation/routesDesc/user/getUserDesc.js Datei anzeigen

@@ -0,0 +1,38 @@
module.exports = {
get: {
tags: ["User"],
description: "Get user by id",
parameters: [
{
name: "id",
in: "path",
schema: {
$ref: "#/components/schemas/id",
},
required: true,
description: "A single user id",
}
],
responses: {
200: {
description: "Success",
content: {
"application/json": {
schema: {
$ref: "#/components/schemas/User",
}
}
}
},
400: {
description: "Bad request"
},
404: {
description: "User with specified id does not exist"
},
500: {
description: "Internal server error"
}
}
}
}

+ 25
- 0
src/documentation/routesDesc/user/getUsersDesc.js Datei anzeigen

@@ -0,0 +1,25 @@
module.exports = {
get: {
tags: ["User"],
description: "Get all users",
parameters: [],
responses: {
200: {
description: "Success",
content: {
"application/json": {
schema: {
$ref: "#/components/schemas/User",
}
}
}
},
200: {
description: "Users returned successfully"
},
500: {
description: "Internal server error"
}
}
}
}

+ 25
- 0
src/documentation/routesDesc/user/updateUserContactsDesc.js Datei anzeigen

@@ -0,0 +1,25 @@
module.exports = {
patch: {
tags: ["User"],
description: "Update user",
parameters: [
{
name: "id",
in: "path",
// schema: {
// $ref: "#/components/schemas/id", // data model of the param
// },
required: true,
description: "A single user id",
}
],
requestBody: {
content: {
}
},
responses: {
}
}
}

+ 48
- 0
src/documentation/routesDesc/user/updateUserDesc.js Datei anzeigen

@@ -0,0 +1,48 @@
module.exports = {
put: {
tags: ["User"],
description: "Update user",
parameters: [
{
name: "id",
in: "path",
schema: {
$ref: "#/components/schemas/id", // data model of the param
},
required: true,
description: "A single user id",
}
],
requestBody: {
content: {
"application/json": {
schema: {
type: "object",
properties: {
name: {
type: "string"
},
email: {
type: "string"
},
password: {
type: "string"
}
}
}
}
}
},
responses: {
200: {
description: "User updated successfully",
},
400: {
description: "Invalid input parameters",
},
500: {
description: "Server error",
}
}
}
}

+ 8
- 0
src/documentation/servers.js Datei anzeigen

@@ -0,0 +1,8 @@
module.exports = {
servers: [
{
url: "http://localhost:3000/",
description: "Local server",
},
],
}

+ 7
- 0
src/documentation/tags.js Datei anzeigen

@@ -0,0 +1,7 @@
module.exports = {
tags: [
{
name: "User"
},
],
}

+ 3
- 3
src/endpoints/token.js Datei anzeigen

@@ -10,11 +10,11 @@ const loginUser = async (req, res, next) => {
}
const isValidPassword = await bcrypt.compare(req.body.password, findUser.password)
if (!isValidPassword) {
return res.status(400).send('Password is incorrect!')
return res.status(400).send('Wrong credentials!')
}
const token = await Token.generateAuthToken(findUser)

return res.send(findUser)
return res.status(201).send(findUser)
} catch (e) {
next(e)
}
@@ -37,7 +37,7 @@ const refreshUserToken = async (req, res) => {
return res.status(404).send('Token not valid!')
}

return res.send('Token ' + result + ' refreshed successfully!')
return res.status(201).send('Token ' + result + ' refreshed successfully!')
}

module.exports = { loginUser, logout, refreshUserToken }

+ 8
- 6
src/endpoints/user.js Datei anzeigen

@@ -16,7 +16,6 @@ const getUser = async (req, res, next) => {
if (!id) {
return res.status(400).send('Bad request')
}

const user = await User.findById(id)
if (!user) {
return res.status(404).send("User with the id of: " + id + " doesnt exist")
@@ -37,7 +36,7 @@ const createUser = async (req, res, next) => {

const err = await User.joiValidate(userModel)
if (err) {
return res.status(400).send(err.message)
return res.status(401).send(err.message)
}

const newUser = new User(userModel)
@@ -67,11 +66,14 @@ const updateUser = async (req, res, next) => {
return res.status(404).send("User with the id of: " + id + " doesnt exist")
}

user.name = objBody.name
user.password = objBody.password
user.email = objBody.email
const updatedUser = {
name: objBody.name,
password: objBody.password,
email: objBody.email
}


await User.updateOne(user)
await User.updateOne({ _id: req.params.id }, updatedUser)

return res.status(200).send('User updated successfully')
} catch (e) {

+ 1
- 44
src/routes/token.js Datei anzeigen

@@ -2,52 +2,9 @@ const express = require('express')
const router = new express.Router()
const endpoints = require('../endpoints/token')

/**
* @openapi
* /auth/token/:
* put:
* description: Log in user
* tags: [Token]
* responses:
* 200:
* description: User logged in successfully!
* 400:
* description: Wrong credentials!
* 500:
* description: Internal server error.
*/
router.post('/auth/token', endpoints.loginUser)

/**
* @openapi
* /auth/logout/:
* put:
* description: Log out user
* tags: [Token]
* responses:
* 200:
* description: User logged out successfully!
* 404:
* description: No user has the token provided!
* 500:
* description: Internal server error.
*/
router.post('/auth/token', endpoints.loginUser)
router.post('/auth/logout', endpoints.logout)

/**
* @openapi
* /auth/refresh/:
* put:
* description: Refresh user token
* tags: [Token]
* responses:
* 200:
* description: Token refreshed successfully!
* 404:
* description: Token not valid!
* 500:
* description: Internal server error.
*/
router.post('/auth/refresh', endpoints.refreshUserToken)

module.exports = router

+ 1
- 93
src/routes/user.js Datei anzeigen

@@ -3,104 +3,12 @@ const endpoints = require('../endpoints/user')
const router = new express.Router()
const auth = require('../middleware/auth')

/**
* @openapi
* /users/:
* get:
* description: Get all users
* tags: [User]
* responses:
* 200:
* description: Success!
* 400:
* description: Bad request.
* 500:
* description: Internal server error.
*/
router.get('/users', auth.authRole, endpoints.getUsers)

/**
* @openapi
* /users/:id:
* get:
* description: Get user by id
* tags: [User]
* responses:
* 200:
* description: Success!
* 400:
* description: Bad request.
* 500:
* description: Internal server error.
*/
router.get('/users', endpoints.getUsers)
router.get('/users/:id', endpoints.getUser)

/**
* @openapi
* /users/:
* post:
* description: Create user
* tags: [User]
* responses:
* 201:
* description: User successfully created!
* 400:
* description: Bad request.
* 500:
* description: Internal server error.
*/
router.post('/users', endpoints.createUser)

/**
* @openapi
* /users/:id:
* put:
* description: Update user
* tags: [User]
* responses:
* 200:
* description: User updated successfully!
* 400:
* description: Invalid input parameters.
* 404:
* description: User not found.
* 500:
* description: Internal server error.
*/
router.put('/users/:id', endpoints.updateUser)

/**
* @openapi
* /users/:id/contacts:
* patch:
* description: Get all users
* tags: [User]
* responses:
* 200:
* description: User contacts updated successfully!
* 404:
* description: User not found.
* 500:
* description: Internal server error.
*/
router.patch('/users/:id/contacts', endpoints.updateUserContacts)

/**
* @openapi
* /users/:id:
* patch:
* description: Delete user
* tags: [User]
* responses:
* 204:
* description: User removed successfully!
* 400:
* description: Id not provided.
* 404:
* description: User not found.
* 500:
* description: Internal server error.
*/
router.delete('/users/:id', endpoints.deleteUser)

module.exports = router

+ 3
- 18
src/server.js Datei anzeigen

@@ -5,35 +5,20 @@ const port = process.env.NODE_ENV === 'production' ? 80 : 3000
require('./database/mongoose')
const userRouter = require('./routes/user')
const tokenRouter = require('./routes/token')
const swaggerJsDoc = require("swagger-jsdoc")
const swaggerUi = require("swagger-ui-express")
const docs = require('./documentation');
const swaggerUI = require("swagger-ui-express")
const { errorLogger, errorResponder } = require('./middleware/errorHandling.js')
const requestLogging = require('./middleware/requestLogging.js')
const cors = require('cors') //Cross-origin resource sharing
const helmet = require('helmet') //Basic protection against attacks like XSS
const config = require('config') //Default configuration file

// console.log(config.util.getEnv('NODE_ENV'))

const swaggerOptions = {
swaggerDefinition: {
info: {
title: 'Diligent node API',
description: 'Diligent node API documentation'
}
},
apis: ['./server.js', './routes/*.js']
}

const swaggerDocs = swaggerJsDoc(swaggerOptions)
app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerDocs))


app.use(express.json())
app.use('/api-docs', swaggerUI.serve, swaggerUI.setup(docs))
app.use(requestLogging)
app.use(cors())
app.use(helmet())

app.use(userRouter)
app.use(tokenRouter)


Laden…
Abbrechen
Speichern