Template
Add user GET endpoint, schemas, and security middlewares
Introduces GET /users/:id endpoint with validation schema, adds tests for user and register routes, and applies security middlewares (helmet, hpp, cors) to the server. Also adds ESLint configuration and updates logger with linting comments.
This commit is contained in:
@@ -16,6 +16,6 @@ It features a **recursive file loader** for routes and schemas, along with a pow
|
||||
|
||||
1. **Clone the repository**
|
||||
```bash
|
||||
git clone https://gitea.azures.fr/azures04/Base-REST-API.git
|
||||
cd Base-REST-API
|
||||
git clone https://gitea.azures.fr/azures04/Base-REST-API.git
|
||||
cd Base-REST-API
|
||||
```
|
||||
@@ -0,0 +1,28 @@
|
||||
const js = require("@eslint/js")
|
||||
const globals = require("globals")
|
||||
|
||||
module.exports = [
|
||||
{
|
||||
ignores: ["node_modules", "logs", "coverage", ".env", "*.log"],
|
||||
},
|
||||
js.configs.recommended,
|
||||
{
|
||||
languageOptions: {
|
||||
ecmaVersion: "latest",
|
||||
sourceType: "commonjs",
|
||||
globals: {
|
||||
...globals.node,
|
||||
...globals.jest,
|
||||
},
|
||||
},
|
||||
rules: {
|
||||
"no-unused-vars": "warn",
|
||||
"no-undef": "error",
|
||||
"eqeqeq": "error",
|
||||
"indent": ["error", 4],
|
||||
"quotes": ["error", "double"],
|
||||
"semi": ["error", "never"],
|
||||
"no-console": "warn",
|
||||
},
|
||||
},
|
||||
]
|
||||
@@ -33,11 +33,13 @@ function write($stream, level, color, content, extraLabels = []) {
|
||||
}
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(`[${date}] `.magenta + `[${level}]`[color] + consoleLabels + " " + message)
|
||||
$stream.write(`[${date}] [${level}]${fileLabels} ${stripColors(message)}\n`)
|
||||
}
|
||||
|
||||
function createLogger(root) {
|
||||
// eslint-disable-next-line no-useless-escape
|
||||
const fileName = (/false/).test(process.env.IS_PROD.toLowerCase()) ? new Date().toLocaleString("fr-FR", { timeZone: "UTC" }).replace(/[\/:]/g, "-").replace(/ /g, "_") : "DEV-LOG"
|
||||
|
||||
const logsDir = path.join(root, "logs")
|
||||
@@ -77,6 +79,7 @@ function stripColors(string) {
|
||||
if (!string || typeof string !== "string") {
|
||||
return string
|
||||
}
|
||||
// eslint-disable-next-line no-control-regex
|
||||
return string.replace(/\x1B\[[0-9;]*[mK]/g, "")
|
||||
}
|
||||
|
||||
|
||||
Generated
+1085
File diff suppressed because it is too large
Load Diff
+8
-1
@@ -17,18 +17,25 @@
|
||||
"scripts": {
|
||||
"start:dev": "nodemon .",
|
||||
"start": "node .",
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
"lint": "eslint .",
|
||||
"lint:fix": "eslint . --fix"
|
||||
},
|
||||
"homepage": "https://gitea.azures.fr/azures04/Base-REST-API",
|
||||
"readme": "https://gitea.azures.fr/azures04/Base-REST-API/src/branch/main/README.md",
|
||||
"dependencies": {
|
||||
"colors": "^1.4.0",
|
||||
"cors": "^2.8.5",
|
||||
"dotenv": "^17.2.3",
|
||||
"express": "^5.2.1",
|
||||
"helmet": "^8.1.0",
|
||||
"hpp": "^0.2.3",
|
||||
"path-to-regexp": "^8.3.0",
|
||||
"zod": "^4.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/js": "^9.39.2",
|
||||
"eslint": "^9.39.2",
|
||||
"globals": "^16.5.0",
|
||||
"nodemon": "^3.1.11"
|
||||
}
|
||||
}
|
||||
|
||||
+8
-12
@@ -2,18 +2,14 @@ const express = require("express")
|
||||
const router = express.Router()
|
||||
const registerService = require("../services/register")
|
||||
|
||||
router.post("/", async (req, res, next) => {
|
||||
try {
|
||||
const { email, username, password } = req.body
|
||||
const registerResult = registerService.register({ email, username, password })
|
||||
return res.status(200).json({
|
||||
code: 200,
|
||||
message: "User successfully registered",
|
||||
data: registerResult
|
||||
})
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
router.post("/", async (req, res) => {
|
||||
const { email, username, password } = req.body
|
||||
const registerResult = registerService.register({ email, username, password })
|
||||
return res.status(200).json({
|
||||
code: 200,
|
||||
message: "User successfully registered",
|
||||
data: registerResult
|
||||
})
|
||||
})
|
||||
|
||||
module.exports = router
|
||||
+11
-2
@@ -1,8 +1,17 @@
|
||||
const express = require("express")
|
||||
const DefaultError = require("../../errors/DefaultError")
|
||||
const router = express.Router()
|
||||
|
||||
router.post("/", async (req, res, next) => {
|
||||
|
||||
router.get("", async (req, res) => {
|
||||
const bearer = req.headers.authorization
|
||||
if (bearer == "Bearer token") {
|
||||
return res.status(200).json({
|
||||
id: req.params.id,
|
||||
username: "johndoe"
|
||||
})
|
||||
} else {
|
||||
throw new DefaultError(403, "Invalid token", "", "InvalidTokenException")
|
||||
}
|
||||
})
|
||||
|
||||
module.exports = router
|
||||
@@ -3,9 +3,6 @@ const z = require("zod")
|
||||
module.exports = {
|
||||
POST: {
|
||||
headers: z.object({
|
||||
authorization: z.string()
|
||||
.startsWith("Bearer ", { message: "Token d'authentification manquant ou invalide." })
|
||||
.optional(),
|
||||
"content-type": z.string().regex(/application\/json/i).optional()
|
||||
}),
|
||||
body: z.object({
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
const z = require("zod")
|
||||
|
||||
module.exports = {
|
||||
GET: {
|
||||
headers: z.object({
|
||||
authorization: z.string()
|
||||
.startsWith("Bearer ", { message: "Token d'authentification manquant ou invalide." }),
|
||||
"content-type": z.string().regex(/application\/json/i).optional()
|
||||
}),
|
||||
error: {
|
||||
code: 422,
|
||||
message: "Invalid request data"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,12 @@
|
||||
const express = require("express")
|
||||
const hpp = require("hpp")
|
||||
const app = express()
|
||||
const cors = require("cors")
|
||||
const path = require("node:path")
|
||||
const utils = require("./modules/utils")
|
||||
const Logger = require("./modules/logger")
|
||||
const logger = Logger.createLogger(__dirname)
|
||||
const utils = require("./modules/utils")
|
||||
const helmet = require("helmet")
|
||||
const loader = require("./modules/loader")
|
||||
const DefaultError = require("./errors/DefaultError")
|
||||
const path2regex = require("path-to-regexp")
|
||||
@@ -13,6 +16,10 @@ const schemas = loader.getRecursiveFiles(path.join(__dirname, "schemas"))
|
||||
|
||||
const schemaRegistry = {}
|
||||
|
||||
app.use(hpp())
|
||||
app.use(helmet())
|
||||
app.use(cors({ origin: "*" }))
|
||||
|
||||
app.use(express.json())
|
||||
app.use(express.urlencoded({ extended: true }))
|
||||
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
const crypto = require("node:crypto")
|
||||
const DefaultError = require("../errors/DefaultError")
|
||||
|
||||
function register({ email, username, password }) {
|
||||
if (true) {
|
||||
function register({ email, username }) {
|
||||
const canRegister = true
|
||||
if (canRegister === true) {
|
||||
return {
|
||||
id: crypto.randomUUID(),
|
||||
username: username,
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
POST http://localhost:3000/register HTTP/1.1
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"email": "johndoe@exemple.com",
|
||||
"username": "johndoe",
|
||||
"password": "Password123"
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
GET http://localhost:3000/users/johndoe HTTP/1.1
|
||||
authorization: Bearer token
|
||||
Reference in New Issue
Block a user