Skip to content

Commit

Permalink
Feature/swagger (#66)
Browse files Browse the repository at this point in the history
* βž• Add >> Swagger added.

* πŸ’„ Swagger >> Link to swagger docs from dev menu.

* 🎨 API >> Creating 'config' object with ports ex.

* πŸ‘½οΈ Swagger >> Adding first swagger configuration. Nothing there yet...

* 🎨 Package.json >> Small module for exporting package.json data as an import.

* 🎨 Swagger >> Optimizing docs config.

* πŸ“ Swagger >> Adding searchbar.

* πŸ“ Swagger >> Adding globe search pattern for routes.

* πŸ“ Swagger >> Adding test docs.

* πŸ“ Swagger >> Test for smaller indent.

* πŸ“ Swagger >> More api routes described.

* πŸ“ Swagger >> Docs for routes added.

* πŸ“ Swagger >> Changed config and route docus.

* πŸ“ Swagger >> Adding first Docs for script APIs.

* πŸ› Scripts >> If a error happens at spawning a script, the response will be a "500" http error.

* πŸ“ Swagger >> Docs for execute script. Not finished.

* πŸ“ Swagger >> Adding Docs for executing scripts.

* πŸ“ Swagger >> Adding description for reading files/folders.

* 🎨 Scripts >> Try/catch for read function added.

* πŸ“ Swagger >> Docs for read route added.

* πŸ“ Swagger >> Adding Tag description.

* πŸ“ Swagger >> Added security tag on different routes.

* 🎨 Scripts >> Added a try/catch opperation for the script download route.

* πŸ“ Swagger >> Adding docs for downloading route.

* πŸ“ Swagger >> Adding docs for adding a new file.

* πŸ“ Swagger >> Adding docs for adding new folder.

* 🎨 Scripts >> Reading/Editing files - Changed param from 'text' to 'content' for better understanding and not mixing two params.

* πŸ“ Swagger >> Added docs for deleting route. Also change paths for adding folder/scripts.

* πŸ“ Swagger >> Adding docs for editing files.

* πŸ“ Swagger >> Adding docs for editing folders.
  • Loading branch information
borsTiHD authored Jul 29, 2021
1 parent 674784d commit d4e6fb2
Show file tree
Hide file tree
Showing 16 changed files with 1,013 additions and 86 deletions.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@
"release-it": "^14.10.0",
"socket.io": "^4.1.3",
"socket.io-client": "^4.1.3",
"swagger-jsdoc": "^6.1.0",
"swagger-ui-express": "^4.1.6",
"vue-socket.io": "^3.0.10",
"vue-toastification": "^1.7.11",
"vuex-persistedstate": "^4.0.0-beta.3",
Expand Down
21 changes: 12 additions & 9 deletions src/api/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,23 +10,26 @@ dotenv.config()

// Config
const isDev = process.env.NODE_ENV === 'development'
const DEV_HOST_IP = process.env.DEV_HOST_IP || 'localhost'
const DEV_PORT_FRONTEND = process.env.DEV_PORT_FRONTEND || DEFAULT.DEV_PORT_FRONTEND // Default Port: 3000
const DEV_PORT_BACKEND = process.env.DEV_PORT_BACKEND || DEFAULT.DEV_PORT_BACKEND // Default Port: 3001
const PORT_PRODUCTION = process.env.PORT_PRODUCTION || DEFAULT.PORT_PRODUCTION // Default: 8800
const config = {
DEV_HOST_IP: process.env.DEV_HOST_IP || 'localhost',
DEV_PORT_FRONTEND: process.env.DEV_PORT_FRONTEND || DEFAULT.DEV_PORT_FRONTEND, // Default Port: 3000
DEV_PORT_BACKEND: process.env.DEV_PORT_BACKEND || DEFAULT.DEV_PORT_BACKEND, // Default Port: 3001
PORT_PRODUCTION: process.env.PORT_PRODUCTION || DEFAULT.PORT_PRODUCTION, // Default: 8800
PORT: null
}

// On dev we use BACKEND port
// On production we use PORT_PRODUCTION
// -> on production we serve front- and backend over the same express server with the same port
const PORT = isDev ? DEV_PORT_BACKEND : PORT_PRODUCTION
config.PORT = isDev ? config.DEV_PORT_BACKEND : config.PORT_PRODUCTION
if (isDev) console.log('[Server] -> Development:', isDev)

// HTTP Server + Socket.IO Server
const app = initExpress(isDev) // Express Server
const app = initExpress(isDev, config) // Express Server
const httpServer = createServer(app) // HTTP Server serving Express + Socket.IO
initSocketIo(httpServer, isDev, DEV_HOST_IP, DEV_PORT_FRONTEND) // Socket.IO Server
initSocketIo(httpServer, isDev, config) // Socket.IO Server

// Server listening on port
httpServer.listen(PORT, () => {
console.log(`[Server] -> App is running on ${PORT}`)
httpServer.listen(config.PORT, () => {
console.log(`[Server] -> App is running on ${config.PORT}`)
})
99 changes: 59 additions & 40 deletions src/api/express/controllers/scripts.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ const execute = asyncHandler(async(req, res, next) => {
// Spawn script
const response = await spawn().catch((error) => {
// REST return
res.json({
res.status(500).json({
_status: 'error',
info: 'Script not successfully executed',
error
Expand Down Expand Up @@ -147,23 +147,32 @@ const read = asyncHandler(async(req, res, next) => {
const query = req.query
const { id, name, type, path } = query

// Scans stats
const stats = await fs.stat(path)

// Not a folder?
if (!stats.isDirectory()) {
// Reading file and return result
const content = await fs.readFile(path, 'utf-8')
res.json({
_status: 'ok',
info: 'File scannt',
script: { id, name, type, path, stats, content }
})
} else {
res.json({
_status: 'ok',
info: 'Folder scannt',
folder: { id, name, type, path, stats }
try {
// Scans stats
const stats = await fs.stat(path)

// Not a folder?
if (!stats.isDirectory()) {
// Reading file and return result
const content = await fs.readFile(path, 'utf-8')
res.json({
_status: 'ok',
info: 'File scannt',
script: { id, name, type, path, stats, content }
})
} else {
res.json({
_status: 'ok',
info: 'Folder scannt',
folder: { id, name, type, path, stats }
})
}
} catch (error) {
// REST return
res.status(500).json({
_status: 'error',
info: 'Script not successfully executed',
error
})
}
})
Expand All @@ -182,29 +191,39 @@ const download = asyncHandler(async(req, res, next) => {
const name = query.name
const filePath = query.path

// Scans stats
const stats = await fs.stat(filePath)

// Not a folder?
if (stats.isFile()) {
// Reading file and return result
res.download(filePath, name)
} else {
const fileName = 'backup.zip'
const archiv = path.join(scriptPath, fileName)
await zipDirectory(filePath, archiv)
await res.download(archiv, fileName)

try {
// Scans stats
const statsBackupFile = await fs.stat(archiv)
if (statsBackupFile.isFile()) {
await fs.unlink(archiv).catch((error) => {
console.error(error)
return next()
})
const stats = await fs.stat(filePath)

// Not a folder?
if (stats.isFile()) {
// Reading file and return result
res.download(filePath, name)
} else {
console.log('[Download] -> tried to delete backup.zip, but nothing happened.')
const fileName = 'backup.zip'
const archiv = path.join(scriptPath, fileName)
await zipDirectory(filePath, archiv)
await res.download(archiv, fileName)

// Scans stats
const statsBackupFile = await fs.stat(archiv)
if (statsBackupFile.isFile()) {
await fs.unlink(archiv).catch((error) => {
console.error(error)
return next()
})
} else {
console.log('[Download] -> tried to delete backup.zip, but nothing happened.')
}
}
} catch (error) {
// Return error
console.error('[Download] -> An error has occurred while downloading a file.')
res.status(500).json({
_status: 'error',
info: 'Could not prepare files, please try again',
error: error.message
})
}
})

Expand All @@ -213,15 +232,15 @@ const download = asyncHandler(async(req, res, next) => {
* @name addFile
* @function
* @memberof module:routers/scripts
* @param {object} data - Object -> form data. Delivers script data: '{ path: "scripts/custom/...", script: { name: "test", ext: "bat", text: "echo test" }}'
* @param {object} data - Object -> form data. Delivers script data: '{ path: "scripts/custom/...", script: { name: "test", ext: "bat", content: "echo test" }}'
*/
const addFile = asyncHandler(async(req, res, next) => {
const data = req.body
const script = data.script
const file = `${script.name}.${script.ext}`
const filePath = path.join(data.path, file)
if (isCustomScript(filePath)) {
await fs.outputFile(filePath, script.text).then(async() => {
await fs.outputFile(filePath, script.content).then(async() => {
console.log('[Add Script] -> Changed executable permissions.')
fs.chmod(filePath, '755')
}).catch((error) => {
Expand Down
14 changes: 13 additions & 1 deletion src/api/express/express.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,14 @@ import createError from 'http-errors'
import express from 'express'
import cors from 'cors'
import cookieParser from 'cookie-parser'
import swaggerJsdoc from 'swagger-jsdoc'
import swaggerUi from 'swagger-ui-express'
import passport from 'passport'
import baseRoutes from './router.js'
import initSwaggerDoc from './swagger.js'

// Exporting Express Setup
export default function(isDev) {
export default function(isDev, config) {
// Config
const DIST_DIR = path.join('dist', 'client')

Expand All @@ -21,6 +24,15 @@ export default function(isDev) {
app.use(cookieParser()) // Cookies
app.use(passport.initialize()) // Authentication

// Swagger Init
const SWAGGER_DOC = initSwaggerDoc(config)
const specs = swaggerJsdoc(SWAGGER_DOC)
app.use(
'/api-docs',
swaggerUi.serve,
swaggerUi.setup(specs, { explorer: true })
)

// Router/Endpoints
const baseUrl = '/api/v1'
baseRoutes(app, baseUrl)
Expand Down
Loading

0 comments on commit d4e6fb2

Please sign in to comment.