Skip to content

Commit

Permalink
Use correct definition for swagger doc
Browse files Browse the repository at this point in the history
Typo correction
  • Loading branch information
bzfvrto authored Jun 17, 2024
2 parents c0aec3b + 13d8ad8 commit 979a424
Show file tree
Hide file tree
Showing 30 changed files with 5,785 additions and 328 deletions.
14 changes: 14 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
APP_NAME=NoPestsAllowed
DB_CONNECTION_STRING=mongodb+srv://.../NoPestsAllowed
ACCESS_TOKEN_SECRET=maSuperPhrasePourHasher

MAIL_MAILER=smtp
MAIL_HOST=smtp.mailtrap.io
MAIL_PORT=2525
MAIL_USERNAME=
MAIL_PASSWORD=

MAIL_FROM_ADDRESS=[email protected]
MAIL_FROM_NAME="${APP_NAME}"

CLOUDINARY_URL=cloudinary://...
29 changes: 29 additions & 0 deletions .github/workflows/jest.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# This workflow will do a clean installation of node dependencies, cache/restore them, build the source code and run tests across different versions of node
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-nodejs

name: JEST tests

on:
push:
branches: ["dev", "test"]
pull_request:
branches: ["main"]

jobs:
build:
runs-on: ubuntu-latest

strategy:
matrix:
node-version: [20.x, 21.x, 22.x]
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/

steps:
- uses: actions/checkout@v4
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
cache: "yarn"
- run: yarn install
- run: yarn test
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -59,3 +59,8 @@ typings/

# next.js build output
.next



# misc files excluded from git
modules/findOrCreatePlace.js
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# NoPestsAllowed : Say stop to bedbugs, flea, bettles...

![example event parameter](https://github.com/NoPestsAllowed/backend/actions/workflows/jest.yml/badge.svg?event=push)

## Backend

This Repository contain the backend powering NoPestsAllowed mobile and web applications.
Expand Down
58 changes: 58 additions & 0 deletions __tests__/routes.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
const request = require("supertest");
const app = require("../app");
const User = require("../models/users");
// const mongoose = require("mongoose");

beforeEach(async () => {
await User.deleteMany({});
global.console = { log: jest.fn() };
});

test("it can register new user", async () => {
const response = await request(app).post("/register").send({
firstname: "John",
lastname: "Doe",
email: "[email protected]",
password: "secret",
});
expect(response.statusCode).toBe(200);
});

test("it can login user", async () => {
await User({
firstname: "John",
lastname: "Doe",
email: "[email protected]",
password: "$2a$10$Qsu.gk.u76oq9Gx4uFq5F.b7JSsrx1/Vh8vROou/9ilZAnNoKniGW", // secret hashed
}).save();
const response = await request(app).post("/login").send({
email: "[email protected]",
password: "secret",
});
expect(response.statusCode).toBe(200);
});

test("an unauthenticated user can not logout", async () => {
const response = await request(app).post("/logout");
expect(response.statusCode).toBe(401);
});

test("it can return all depositions", async () => {
const response = await request(app).get("/depositions");
expect(response.statusCode).toBe(200);
expect(response.body.result).toBe(true);
response.body.depositions.map((deposition) => {
expect(deposition).toHaveProperty("_id");
expect(deposition).toHaveProperty("name");
expect(deposition).toHaveProperty("description");
expect(deposition).toHaveProperty("status");
expect(deposition).toHaveProperty("type");
expect(deposition).toHaveProperty("visualProofs");
expect(deposition).toHaveProperty("placeOwnerEmail");
expect(deposition).toHaveProperty("placeId");
expect(deposition.placeId).toHaveProperty("_id");
expect(deposition.placeId).toHaveProperty("address");
expect(deposition.placeId).toHaveProperty("geojson");
expect(deposition.placeId).toHaveProperty("type");
});
});
15 changes: 15 additions & 0 deletions __tests__/utils/globalSetup.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
const mongoose = require("mongoose");
const { MongoMemoryServer } = require("mongodb-memory-server");

module.exports = async function globalSetup() {
const instance = await MongoMemoryServer.create();
const uri = instance.getUri();
global.__MONGOINSTANCE = instance;
process.env.DB_CONNECTION_STRING = uri.slice(0, uri.lastIndexOf("/"));

// The following is to make sure the database is clean before an test starts
const conn = await mongoose.connect(`${instance.getUri()}`, { dbName: "npa_test_db" });
await conn.connection.db.dropDatabase();
await mongoose.disconnect();
process.env.ACCESS_TOKEN_SECRET = "maSuperPhrasePourHasher";
};
7 changes: 7 additions & 0 deletions __tests__/utils/globalTeardown.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
const mongoose = require("mongoose");
const { MongoMemoryServer } = require("mongodb-memory-server");

module.exports = async function globalTeardown() {
const instance = global.__MONGOINSTANCE;
await instance.stop();
};
12 changes: 12 additions & 0 deletions __tests__/utils/setup.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
const mongoose = require("mongoose");

beforeAll(async () => {
// put your client connection code here, example with mongoose:
await mongoose.disconnect();
await mongoose.connect(process.env["DB_CONNECTION_STRING"]);
});

afterAll(async () => {
// put your client disconnection code here, example with mongodb:
await mongoose.disconnect();
});
53 changes: 52 additions & 1 deletion app.js
Original file line number Diff line number Diff line change
@@ -1,26 +1,77 @@
require("dotenv").config();
require("./models/connection");

// Documentation
const swaggerUi = require("swagger-ui-express");
const swaggerFile = require("./swagger-output.json");

const authenticateUser = require("./routes/middleware/authenticateUser");

var express = require("express");
var path = require("path");
var cookieParser = require("cookie-parser");
var logger = require("morgan");

const bodyParser = require("body-parser");

var indexRouter = require("./routes/index");
var usersRouter = require("./routes/users");
var depositionsRouter = require("./routes/depositions");
var mailRouter = require("./routes/mail");

var app = express();

const cors = require("cors");

const corsOptions = {
origin: function (origin, callback) {
// Remplacee 'allowedOrigins' avec vos différents URLs front pouvant accéder au Backend
const allowedOrigins = [
// "http://localhost:4000",
"http://localhost:3001",
"http://192.168.100.145:3000",
"http://192.168.100.145:3001",
"http://192.168.100.145:8081",
`http://${process.env.FRONTEND_URL}`,
`https://${process.env.FRONTEND_URL}`,
];
if (allowedOrigins.includes(origin) || !origin) {
callback(null, true);
} else {
callback(new Error("Not allowed by CORS"));
}
},
allowedHeaders: ["Origin", "X-Requested-With", "Content-Type", "Accept"],
methods: ["GET", "POST", "PUT", "DELETE"],
};
app.use(cors(corsOptions));

app.use(logger("dev"));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(cookieParser(process.env.ACCESS_TOKEN_SECRET));
app.use(express.static(path.join(__dirname, "public")));

app.use(bodyParser.urlencoded({ extended: true }));
app.use(
"/doc",
swaggerUi.serve,
swaggerUi.setup(swaggerFile, {
customJs: [
"https://cdnjs.cloudflare.com/ajax/libs/swagger-ui/4.15.5/swagger-ui-bundle.min.js",
"https://cdnjs.cloudflare.com/ajax/libs/swagger-ui/4.15.5/swagger-ui-standalone-preset.min.js",
],
customCssUrl: [
"https://cdnjs.cloudflare.com/ajax/libs/swagger-ui/4.15.5/swagger-ui.min.css",
"https://cdnjs.cloudflare.com/ajax/libs/swagger-ui/4.15.5/swagger-ui-standalone-preset.min.css",
"https://cdnjs.cloudflare.com/ajax/libs/swagger-ui/4.15.5/swagger-ui.css",
],
})
);

app.use("/", indexRouter);
app.use("/mail", mailRouter);
// app.use(authenticateUser);
app.use("/users", usersRouter);
app.use("/depositions", depositionsRouter);

Expand Down
1 change: 1 addition & 0 deletions dataset/pests.json

Large diffs are not rendered by default.

12 changes: 12 additions & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
const fs = require("node:fs");
/** @type {import('jest').Config} */
const config = {
verbose: true,
testEnvironment: "node",
modulePathIgnorePatterns: ["__tests__/utils/*"],
globalSetup: "./__tests__/utils/globalSetup.js",
globalTeardown: "./__tests__/utils/globalTeardown.js",
setupFilesAfterEnv: ["./__tests__/utils/setup.js"],
};

module.exports = config;
11 changes: 11 additions & 0 deletions models/depositions.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,17 @@ const depositionSchema = mongoose.Schema({
type: [visualProofSchema],
required: false,
},
status: {
type: String,
default: "pending",
enum: ["pending", "accepted", "rejected", "resolved"],
},
type: {
type: String,
required: true,
// default: null,
// enum: ["pending", "accepted", "rejected", "resolved"],
},
publishedAt: {
type: Date,
required: false,
Expand Down
15 changes: 12 additions & 3 deletions models/places.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
const mongoose = require("mongoose");

const geojsonSchema = new mongoose.Schema({
const GeoJson = new mongoose.Schema({
type: {
type: String,
enum: ["Point", "Polygon", "LineString", "MultiLineString", "MultiPolygon"],
Expand All @@ -19,8 +19,9 @@ const placeSchema = mongoose.Schema({
unique: false,
},
geojson: {
type: geojsonSchema,
type: GeoJson,
required: true,
index: true,
},
type: {
type: String,
Expand All @@ -36,8 +37,16 @@ const placeSchema = mongoose.Schema({
ref: "owners",
required: false,
},
uniqRef: {
type: String,
required: true,
},
});

placeSchema.index({ geojson: "2dsphere" });
const Place = mongoose.model("places", placeSchema);
// const GeoJson = mongoose.model("geojsons", geojsonSchema);

// Place.index({ geojson: "2dsphere" });

module.exports = Place;
module.exports = { Place, GeoJson };
8 changes: 7 additions & 1 deletion models/resolutions.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
const mongoose = require("mongoose");
const visualProofSchema = require("./visualProofs");

const resolutionSchema = mongoose.Schema({
// Foreign Keys
Expand All @@ -21,7 +22,12 @@ const resolutionSchema = mongoose.Schema({
},
status: {
type: String,
// enum: ['pending', 'accepted', 'refused']
default: "pending",
enum: ["pending", "accepted", "refused"],
},
text: {
type: String,
required: false,
},
});

Expand Down
35 changes: 28 additions & 7 deletions modules/generateAccessAndRefreshToken.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,35 @@
const jwt = require("jsonwebtoken");

const generateAccessAndRefreshToken = (email) => {
const accessToken = jwt.sign({ email: email }, process.env.ACCESS_TOKEN_SECRET, {
expiresIn: "10s",
});
const refreshToken = jwt.sign({ email: email }, process.env.ACCESS_TOKEN_SECRET, {
expiresIn: "1d",
const generateAccessAndRefreshToken = (payload) => {
const accessToken = generateAccessToken({ ...payload });
const refreshToken = jwt.sign({ ...payload }, process.env.ACCESS_TOKEN_SECRET, {
expiresIn: "10d",
});

return [accessToken, refreshToken];
};

module.exports = { generateAccessAndRefreshToken };
const generateAccessToken = (payload) => {
return jwt.sign({ ...payload }, process.env.ACCESS_TOKEN_SECRET, {
// expiresIn: "10d",
});
};

const clearTokens = async (req, res) => {
const { signedCookies = {} } = req;
const { refreshToken } = signedCookies;
if (refreshToken) {
const tokenFromDB = await refreshToken.findOne({ refreshToken });
if (tokenFromDB) {
console.log("revocking token from db");
tokenFromDB.update({ revokedAt: Date.now() });
}
}
res.clearCookie("nopestsallowed_jwt", {
httpOnly: true,
secure: false,
signed: true,
});
};

module.exports = { generateAccessAndRefreshToken, generateAccessToken, clearTokens };
Loading

0 comments on commit 979a424

Please sign in to comment.