first commit
This commit is contained in:
8
.dockerignore
Normal file
8
.dockerignore
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
node_modules
|
||||||
|
npm-debug.log
|
||||||
|
Dockerfile
|
||||||
|
docker-compose.yml
|
||||||
|
.git
|
||||||
|
.gitignore
|
||||||
|
.env
|
||||||
|
|
||||||
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
node_modules
|
||||||
|
.env
|
||||||
|
uploads/
|
||||||
9
Dockerfile
Normal file
9
Dockerfile
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
FROM node:20-alpine
|
||||||
|
WORKDIR /app
|
||||||
|
COPY package*.json ./
|
||||||
|
RUN npm ci --omit=dev
|
||||||
|
COPY . .
|
||||||
|
ENV PORT=3000
|
||||||
|
EXPOSE 3000
|
||||||
|
CMD ["npm", "start"]
|
||||||
|
|
||||||
21
docker-compose.yml
Normal file
21
docker-compose.yml
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
services:
|
||||||
|
api:
|
||||||
|
build: .
|
||||||
|
ports:
|
||||||
|
- "3000:3000"
|
||||||
|
environment:
|
||||||
|
- PORT=3000
|
||||||
|
- MONGODB_URI=mongodb://appuser:apppass@mongo:27017/inspect?authSource=admin
|
||||||
|
depends_on:
|
||||||
|
- mongo
|
||||||
|
mongo:
|
||||||
|
image: mongo:7
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
- MONGO_INITDB_ROOT_USERNAME=appuser
|
||||||
|
- MONGO_INITDB_ROOT_PASSWORD=apppass
|
||||||
|
- MONGO_INITDB_DATABASE=inspect
|
||||||
|
volumes:
|
||||||
|
- mongo-data:/data/db
|
||||||
|
volumes:
|
||||||
|
mongo-data:
|
||||||
27
lib/jwtUtils.js
Normal file
27
lib/jwtUtils.js
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
const jwt = require("jsonwebtoken");
|
||||||
|
|
||||||
|
const generateToken = (userId) => {
|
||||||
|
const token = jwt.sign({ userId }, "[)51k:7W71Ki+^p:;XxE4LQ£-I@B49", {
|
||||||
|
expiresIn: "7d",
|
||||||
|
});
|
||||||
|
return token;
|
||||||
|
};
|
||||||
|
|
||||||
|
const verifyToken = (req, res, next) => {
|
||||||
|
const token = req.headers.authorization;
|
||||||
|
|
||||||
|
if (!token) {
|
||||||
|
return res.status(401).json({ message: "Unauthorized: Token missing" });
|
||||||
|
}
|
||||||
|
|
||||||
|
jwt.verify(token, "[)51k:7W71Ki+^p:;XxE4LQ£-I@B49", (err, decoded) => {
|
||||||
|
if (err) {
|
||||||
|
return res.status(401).json({ message: "Unauthorized: Invalid token" });
|
||||||
|
}
|
||||||
|
|
||||||
|
req.userId = decoded.userId;
|
||||||
|
next();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = { generateToken, verifyToken };
|
||||||
89
models/Inspect.js
Normal file
89
models/Inspect.js
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
const mongoose = require("mongoose");
|
||||||
|
|
||||||
|
const inspectSchema = new mongoose.Schema(
|
||||||
|
{
|
||||||
|
place_key: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
user_id: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
province: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
license_type: {
|
||||||
|
type: String,
|
||||||
|
required: false,
|
||||||
|
},
|
||||||
|
document_number: {
|
||||||
|
type: String,
|
||||||
|
required: false,
|
||||||
|
},
|
||||||
|
issuer: {
|
||||||
|
type: String,
|
||||||
|
required: false,
|
||||||
|
},
|
||||||
|
economic_code: {
|
||||||
|
type: String,
|
||||||
|
required: false,
|
||||||
|
},
|
||||||
|
registration_number: {
|
||||||
|
type: String,
|
||||||
|
required: false,
|
||||||
|
},
|
||||||
|
ownership_type: {
|
||||||
|
type: String,
|
||||||
|
required: false,
|
||||||
|
},
|
||||||
|
unit_type: {
|
||||||
|
type: String,
|
||||||
|
required: false,
|
||||||
|
},
|
||||||
|
description: {
|
||||||
|
type: String,
|
||||||
|
required: false,
|
||||||
|
},
|
||||||
|
violation_amount: {
|
||||||
|
type: String,
|
||||||
|
required: false,
|
||||||
|
},
|
||||||
|
plaintiff_damage: {
|
||||||
|
type: String,
|
||||||
|
required: false,
|
||||||
|
},
|
||||||
|
infractions: {
|
||||||
|
type: [
|
||||||
|
{
|
||||||
|
title: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
description: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
required: false,
|
||||||
|
},
|
||||||
|
inspectors: {
|
||||||
|
type: [
|
||||||
|
{
|
||||||
|
fullname: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
required: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{ timestamps: true }
|
||||||
|
);
|
||||||
|
|
||||||
|
const Place = mongoose.model("Inspect", inspectSchema);
|
||||||
|
|
||||||
|
module.exports = Place;
|
||||||
13
models/UpdateData.js
Normal file
13
models/UpdateData.js
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
const mongoose = require("mongoose");
|
||||||
|
|
||||||
|
const UpdateDataSchema = new mongoose.Schema({
|
||||||
|
records: {
|
||||||
|
type: Map,
|
||||||
|
of: [mongoose.Schema.Types.Mixed],
|
||||||
|
default: {},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const UpdateData = mongoose.model("UpdateData", UpdateDataSchema);
|
||||||
|
|
||||||
|
module.exports = UpdateData;
|
||||||
48
models/herd.js
Normal file
48
models/herd.js
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
const mongoose = require("mongoose");
|
||||||
|
|
||||||
|
const inspectSchema = new mongoose.Schema({
|
||||||
|
agent: {
|
||||||
|
type: String,
|
||||||
|
required: false,
|
||||||
|
},
|
||||||
|
birth_day: {
|
||||||
|
type: String,
|
||||||
|
required: false,
|
||||||
|
},
|
||||||
|
contractor_code: {
|
||||||
|
type: String,
|
||||||
|
required: false,
|
||||||
|
},
|
||||||
|
gender: {
|
||||||
|
type: String,
|
||||||
|
required: false,
|
||||||
|
},
|
||||||
|
herd_code: {
|
||||||
|
type: String,
|
||||||
|
required: false,
|
||||||
|
},
|
||||||
|
national_id_livestock_code: {
|
||||||
|
type: String,
|
||||||
|
required: false,
|
||||||
|
},
|
||||||
|
registering_date: {
|
||||||
|
type: String,
|
||||||
|
required: false,
|
||||||
|
},
|
||||||
|
registering_user: {
|
||||||
|
type: String,
|
||||||
|
required: false,
|
||||||
|
},
|
||||||
|
type: {
|
||||||
|
type: String,
|
||||||
|
required: false,
|
||||||
|
},
|
||||||
|
unique_identifier: {
|
||||||
|
type: String,
|
||||||
|
required: false,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const Herd = mongoose.model("Herds", inspectSchema);
|
||||||
|
|
||||||
|
module.exports = Herd;
|
||||||
36
models/peopleInfo.js
Normal file
36
models/peopleInfo.js
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
const mongoose = require("mongoose");
|
||||||
|
|
||||||
|
const peopleInfoSchema = new mongoose.Schema(
|
||||||
|
{
|
||||||
|
mobile: { type: String, required: false, index: true },
|
||||||
|
name: { type: String, required: false, index: true },
|
||||||
|
family: { type: String, required: false, index: true },
|
||||||
|
birthdate: { type: String, required: false },
|
||||||
|
nationalcode: { type: String, required: false, index: true },
|
||||||
|
mellicard: { type: String, required: false },
|
||||||
|
info1: { type: String, required: false },
|
||||||
|
info2: { type: String, required: false },
|
||||||
|
info3: { type: String, required: false },
|
||||||
|
info4: { type: String, required: false },
|
||||||
|
},
|
||||||
|
{ timestamps: false }
|
||||||
|
);
|
||||||
|
|
||||||
|
peopleInfoSchema.index({ nationalcode: 1 });
|
||||||
|
peopleInfoSchema.index({ mobile: 1 });
|
||||||
|
peopleInfoSchema.index({ name: 1, family: 1 });
|
||||||
|
|
||||||
|
peopleInfoSchema.index(
|
||||||
|
{ name: "text", family: "text" },
|
||||||
|
{
|
||||||
|
default_language: "none",
|
||||||
|
weights: { name: 10, family: 10 },
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
peopleInfoSchema.index({ name: 1 });
|
||||||
|
peopleInfoSchema.index({ family: 1 });
|
||||||
|
|
||||||
|
const PeopleInfo = mongoose.model("PeopleInfo", peopleInfoSchema);
|
||||||
|
|
||||||
|
module.exports = PeopleInfo;
|
||||||
27
models/place.js
Normal file
27
models/place.js
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
const mongoose = require("mongoose");
|
||||||
|
|
||||||
|
const placeSchema = new mongoose.Schema(
|
||||||
|
{
|
||||||
|
name: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
description: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
location: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
category: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{ timestamps: true }
|
||||||
|
);
|
||||||
|
|
||||||
|
const Place = mongoose.model("Place", placeSchema);
|
||||||
|
|
||||||
|
module.exports = Place;
|
||||||
15
models/user.js
Normal file
15
models/user.js
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
const mongoose = require("mongoose");
|
||||||
|
|
||||||
|
const userSchema = new mongoose.Schema({
|
||||||
|
mobile: { type: String, required: true, unique: true },
|
||||||
|
password: { type: String, required: true },
|
||||||
|
fullname: { type: String, required: true, unique: false },
|
||||||
|
pic: { type: String, required: false },
|
||||||
|
province: { type: String, required: true },
|
||||||
|
city: { type: String, required: false },
|
||||||
|
permissions: { type: Array, default: ["all"], required: false },
|
||||||
|
});
|
||||||
|
|
||||||
|
const User = mongoose.model("User", userSchema);
|
||||||
|
|
||||||
|
module.exports = User;
|
||||||
2134
package-lock.json
generated
Normal file
2134
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
25
package.json
Normal file
25
package.json
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
{
|
||||||
|
"dependencies": {
|
||||||
|
"axios": "^1.7.7",
|
||||||
|
"bcrypt": "^5.1.1",
|
||||||
|
"cors": "^2.8.5",
|
||||||
|
"dotenv": "^17.2.3",
|
||||||
|
"express": "^4.18.2",
|
||||||
|
"jsonstream": "^1.0.3",
|
||||||
|
"JSONStream": "^1.3.5",
|
||||||
|
"jsonwebtoken": "^9.0.2",
|
||||||
|
"mongodb": "^6.3.0",
|
||||||
|
"mongoose": "^8.0.3",
|
||||||
|
"oboe": "^2.1.7",
|
||||||
|
"querystring": "^0.2.1",
|
||||||
|
"stream-json": "^1.9.1"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"start": "node server.js",
|
||||||
|
"dev": "nodemon server.js",
|
||||||
|
"devStart": "nodemon server.js"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"nodemon": "^3.0.2"
|
||||||
|
}
|
||||||
|
}
|
||||||
54
routes/herdRoutes.js
Normal file
54
routes/herdRoutes.js
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
const express = require("express");
|
||||||
|
const router = express.Router();
|
||||||
|
const Herd = require("../models/herd");
|
||||||
|
const { verifyToken } = require("../lib/jwtUtils");
|
||||||
|
|
||||||
|
router.post("/herds", async (req, res) => {
|
||||||
|
try {
|
||||||
|
const {
|
||||||
|
agent,
|
||||||
|
birth_day,
|
||||||
|
contractor_code,
|
||||||
|
gender,
|
||||||
|
herd_code,
|
||||||
|
national_id_livestock_code,
|
||||||
|
registering_date,
|
||||||
|
registering_user,
|
||||||
|
type,
|
||||||
|
unique_identifier,
|
||||||
|
} = req.body;
|
||||||
|
|
||||||
|
const newHerd = new Herd({
|
||||||
|
agent,
|
||||||
|
birth_day,
|
||||||
|
contractor_code,
|
||||||
|
gender,
|
||||||
|
herd_code,
|
||||||
|
national_id_livestock_code,
|
||||||
|
registering_date,
|
||||||
|
registering_user,
|
||||||
|
type,
|
||||||
|
unique_identifier,
|
||||||
|
});
|
||||||
|
|
||||||
|
const savedHerd = await newHerd.save();
|
||||||
|
|
||||||
|
res.status(201).json(savedHerd);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error creating herd:", error);
|
||||||
|
res.status(500).json({ message: "Internal Server Error" });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
router.get("/herds", async (req, res) => {
|
||||||
|
try {
|
||||||
|
const herds = await Herd.find();
|
||||||
|
|
||||||
|
res.status(200).json(herds);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error retrieving herds:", error);
|
||||||
|
res.status(500).json({ message: "Internal Server Error" });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = router;
|
||||||
225
routes/inspectRoutes.js
Normal file
225
routes/inspectRoutes.js
Normal file
@@ -0,0 +1,225 @@
|
|||||||
|
const express = require("express");
|
||||||
|
const router = express.Router();
|
||||||
|
const Inspect = require("../models/Inspect");
|
||||||
|
const { verifyToken } = require("../lib/jwtUtils");
|
||||||
|
|
||||||
|
router.use(verifyToken);
|
||||||
|
router.post("/inspections", async (req, res) => {
|
||||||
|
try {
|
||||||
|
const {
|
||||||
|
place_key,
|
||||||
|
province,
|
||||||
|
license_type,
|
||||||
|
document_number,
|
||||||
|
issuer,
|
||||||
|
economic_code,
|
||||||
|
registration_number,
|
||||||
|
ownership_type,
|
||||||
|
unit_type,
|
||||||
|
description,
|
||||||
|
infractions,
|
||||||
|
violation_amount,
|
||||||
|
plaintiff_damage,
|
||||||
|
inspectors,
|
||||||
|
user_id,
|
||||||
|
} = req.body;
|
||||||
|
const newInspection = new Inspect({
|
||||||
|
place_key,
|
||||||
|
province,
|
||||||
|
license_type,
|
||||||
|
document_number,
|
||||||
|
issuer,
|
||||||
|
economic_code,
|
||||||
|
registration_number,
|
||||||
|
ownership_type,
|
||||||
|
unit_type,
|
||||||
|
description,
|
||||||
|
infractions,
|
||||||
|
violation_amount,
|
||||||
|
plaintiff_damage,
|
||||||
|
inspectors,
|
||||||
|
user_id,
|
||||||
|
});
|
||||||
|
await newInspection.save();
|
||||||
|
|
||||||
|
res.status(201).json({
|
||||||
|
message: "inspection created successfully",
|
||||||
|
place: newInspection,
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error creating inspection:", error);
|
||||||
|
res.status(500).json({ message: "Internal Server Error" });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
router.get("/inspections/:place_key", async (req, res) => {
|
||||||
|
try {
|
||||||
|
const placeId = req.params.place_key;
|
||||||
|
const inspections = await Inspect.find({ place_key: placeId }).sort({
|
||||||
|
createdAt: -1,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!inspections || inspections.length === 0) {
|
||||||
|
return res
|
||||||
|
.status(404)
|
||||||
|
.json({ message: "Inspections not found for this place" });
|
||||||
|
}
|
||||||
|
|
||||||
|
res.status(200).json(inspections);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error retrieving inspections:", error);
|
||||||
|
res.status(500).json({ message: "Internal Server Error" });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
router.get("/userinspections/:userInspects", async (req, res) => {
|
||||||
|
try {
|
||||||
|
const userInspects = req.params.userInspects;
|
||||||
|
const inspections = await Inspect.find({ user_id: userInspects }).sort({
|
||||||
|
createdAt: -1,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!inspections || inspections.length === 0) {
|
||||||
|
return res
|
||||||
|
.status(404)
|
||||||
|
.json({ message: "Inspections not found for this user" });
|
||||||
|
}
|
||||||
|
|
||||||
|
res.status(200).json(inspections);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error retrieving inspections:", error);
|
||||||
|
res.status(500).json({ message: "Internal Server Error" });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
router.get("/inspects", async (req, res) => {
|
||||||
|
try {
|
||||||
|
const places = await Inspect.find().sort({ createdAt: -1 });
|
||||||
|
|
||||||
|
res.status(200).json(places);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error retrieving inspects:", error);
|
||||||
|
res.status(500).json({ message: "Internal Server Error" });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
router.get("/inspectkeys", async (req, res) => {
|
||||||
|
try {
|
||||||
|
const places = await Inspect.find()
|
||||||
|
.select("place_key infractions")
|
||||||
|
.sort({ createdAt: -1 });
|
||||||
|
|
||||||
|
const placesWithInfractions = places.map((place) => ({
|
||||||
|
place_key: place.place_key,
|
||||||
|
hasInfractions: place.infractions.length > 0,
|
||||||
|
}));
|
||||||
|
|
||||||
|
res.status(200).json(placesWithInfractions);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error retrieving inspects:", error);
|
||||||
|
res.status(500).json({ message: "Internal Server Error" });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
router.delete("/inspections/:inspectId", async (req, res) => {
|
||||||
|
try {
|
||||||
|
const inspectId = req.params.inspectId;
|
||||||
|
|
||||||
|
const deletedPlace = await Inspect.findByIdAndDelete(inspectId);
|
||||||
|
|
||||||
|
if (!deletedPlace) {
|
||||||
|
return res.status(404).json({ message: "Inspection not found" });
|
||||||
|
}
|
||||||
|
|
||||||
|
res.status(200).json({
|
||||||
|
message: "Inspection deleted successfully",
|
||||||
|
place: deletedPlace,
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error deleting inspection:", error);
|
||||||
|
res.status(500).json({ message: "Internal Server Error" });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
router.delete(
|
||||||
|
"/inspections/:id/infractions/:infractionId",
|
||||||
|
async (req, res) => {
|
||||||
|
const inspectId = req.params.id;
|
||||||
|
const infractionId = req.params.infractionId;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const inspect = await Inspect.findById(inspectId);
|
||||||
|
|
||||||
|
if (!inspect) {
|
||||||
|
return res.status(404).json({ message: "Place not found" });
|
||||||
|
}
|
||||||
|
|
||||||
|
inspect.infractions.pull({ _id: infractionId });
|
||||||
|
|
||||||
|
await inspect.save();
|
||||||
|
|
||||||
|
res.status(200).json({ message: "Infraction deleted successfully" });
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error deleting infraction:", error);
|
||||||
|
res.status(500).json({ message: "Internal Server Error" });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
//routes
|
||||||
|
|
||||||
|
router.put("/inspections/:inspectionId", async (req, res) => {
|
||||||
|
try {
|
||||||
|
const inspectionId = req.params.inspectionId;
|
||||||
|
const {
|
||||||
|
place_key,
|
||||||
|
province,
|
||||||
|
license_type,
|
||||||
|
document_number,
|
||||||
|
issuer,
|
||||||
|
economic_code,
|
||||||
|
registration_number,
|
||||||
|
ownership_type,
|
||||||
|
unit_type,
|
||||||
|
description,
|
||||||
|
infractions,
|
||||||
|
violation_amount,
|
||||||
|
plaintiff_damage,
|
||||||
|
inspectors,
|
||||||
|
} = req.body;
|
||||||
|
|
||||||
|
const updatedPlace = await Inspect.findByIdAndUpdate(
|
||||||
|
inspectionId,
|
||||||
|
{
|
||||||
|
place_key,
|
||||||
|
province,
|
||||||
|
license_type,
|
||||||
|
document_number,
|
||||||
|
issuer,
|
||||||
|
economic_code,
|
||||||
|
registration_number,
|
||||||
|
ownership_type,
|
||||||
|
unit_type,
|
||||||
|
description,
|
||||||
|
infractions,
|
||||||
|
violation_amount,
|
||||||
|
plaintiff_damage,
|
||||||
|
inspectors,
|
||||||
|
},
|
||||||
|
{ new: true }
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!updatedPlace) {
|
||||||
|
return res.status(404).json({ message: "Inspection not found" });
|
||||||
|
}
|
||||||
|
|
||||||
|
res.status(200).json({
|
||||||
|
message: "Inspection updated successfully",
|
||||||
|
place: updatedPlace,
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error updating Inspection:", error);
|
||||||
|
res.status(500).json({ message: "Internal Server Error" });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = router;
|
||||||
543
routes/nationalDocumentsRoutes.js
Normal file
543
routes/nationalDocumentsRoutes.js
Normal file
@@ -0,0 +1,543 @@
|
|||||||
|
const express = require("express");
|
||||||
|
const router = express.Router();
|
||||||
|
const https = require("https");
|
||||||
|
const querystring = require("querystring");
|
||||||
|
const zlib = require("zlib");
|
||||||
|
const { verifyToken } = require("../lib/jwtUtils");
|
||||||
|
|
||||||
|
function getRandomElement(array) {
|
||||||
|
const randomIndex = Math.floor(Math.random() * array.length);
|
||||||
|
return array[randomIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseBaJsonResponse(response, rawBuffer) {
|
||||||
|
const encoding = String(response.headers["content-encoding"] || "")
|
||||||
|
.trim()
|
||||||
|
.toLowerCase();
|
||||||
|
|
||||||
|
let buf = rawBuffer;
|
||||||
|
|
||||||
|
if (encoding === "gzip") {
|
||||||
|
buf = zlib.gunzipSync(buf);
|
||||||
|
} else if (encoding === "deflate") {
|
||||||
|
buf = zlib.inflateSync(buf);
|
||||||
|
} else if (encoding === "br") {
|
||||||
|
buf = zlib.brotliDecompressSync(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
return JSON.parse(buf.toString("utf8"));
|
||||||
|
}
|
||||||
|
|
||||||
|
async function performLogin() {
|
||||||
|
const getOptions = {
|
||||||
|
hostname: "ba124.ir",
|
||||||
|
path: "/Account/Login",
|
||||||
|
method: "GET",
|
||||||
|
headers: {
|
||||||
|
"User-Agent":
|
||||||
|
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36",
|
||||||
|
Accept: "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
|
||||||
|
"Accept-Language": "en-US,en;q=0.9,fa-IR;q=0.8,fa;q=0.7",
|
||||||
|
Connection: "keep-alive",
|
||||||
|
"Sec-Fetch-Dest": "document",
|
||||||
|
"Sec-Fetch-Mode": "navigate",
|
||||||
|
"Sec-Fetch-Site": "none",
|
||||||
|
"Sec-Fetch-User": "?1",
|
||||||
|
"Upgrade-Insecure-Requests": "1",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const loginPageCookies = await new Promise((resolve, reject) => {
|
||||||
|
const request = https.request(getOptions, (response) => {
|
||||||
|
let data = "";
|
||||||
|
|
||||||
|
response.on("data", (chunk) => {
|
||||||
|
data += chunk;
|
||||||
|
});
|
||||||
|
|
||||||
|
response.on("end", () => {
|
||||||
|
const csrfMatch = data.match(
|
||||||
|
/<input name="__RequestVerificationToken" type="hidden" value="([^"]+)"/
|
||||||
|
);
|
||||||
|
const csrfToken = csrfMatch ? csrfMatch[1] : null;
|
||||||
|
|
||||||
|
if (!csrfToken) {
|
||||||
|
reject(new Error("Could not extract CSRF token"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const cookies = response.headers["set-cookie"] || [];
|
||||||
|
const cookieString = cookies
|
||||||
|
.map((cookie) => cookie.split(";")[0])
|
||||||
|
.join("; ");
|
||||||
|
|
||||||
|
resolve({ csrfToken, cookieString });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
request.on("error", (error) => {
|
||||||
|
reject(error);
|
||||||
|
});
|
||||||
|
|
||||||
|
request.end();
|
||||||
|
});
|
||||||
|
|
||||||
|
const randomUser = getRandomElement([
|
||||||
|
4072893341, 4072452238, 4070413170, 4189617652, 4071417919, 4172069355,
|
||||||
|
]);
|
||||||
|
|
||||||
|
const postData = querystring.stringify({
|
||||||
|
NationalId: randomUser,
|
||||||
|
Password: randomUser,
|
||||||
|
__RequestVerificationToken: loginPageCookies.csrfToken,
|
||||||
|
});
|
||||||
|
|
||||||
|
const postOptions = {
|
||||||
|
hostname: "ba124.ir",
|
||||||
|
path: "/Account/Login",
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
|
||||||
|
"Content-Length": Buffer.byteLength(postData),
|
||||||
|
"User-Agent":
|
||||||
|
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36",
|
||||||
|
Accept: "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
|
||||||
|
"Accept-Language": "en-US,en;q=0.9,fa-IR;q=0.8,fa;q=0.7",
|
||||||
|
Connection: "keep-alive",
|
||||||
|
Cookie: loginPageCookies.cookieString,
|
||||||
|
Host: "ba124.ir",
|
||||||
|
Origin: "https://ba124.ir",
|
||||||
|
Referer: "https://ba124.ir/Account/Login",
|
||||||
|
"Sec-Fetch-Dest": "document",
|
||||||
|
"Sec-Fetch-Mode": "navigate",
|
||||||
|
"Sec-Fetch-Site": "same-origin",
|
||||||
|
"Sec-Fetch-User": "?1",
|
||||||
|
"Upgrade-Insecure-Requests": "1",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const finalCookie = await new Promise((resolve, reject) => {
|
||||||
|
const request = https.request(postOptions, (response) => {
|
||||||
|
response.on("data", () => {});
|
||||||
|
|
||||||
|
response.on("end", () => {
|
||||||
|
const cookies = response.headers["set-cookie"] || [];
|
||||||
|
const cookieString = cookies
|
||||||
|
.map((cookie) => cookie.split(";")[0])
|
||||||
|
.join("; ");
|
||||||
|
|
||||||
|
const combinedCookie = loginPageCookies.cookieString
|
||||||
|
? `${loginPageCookies.cookieString}; ${cookieString}`
|
||||||
|
: cookieString;
|
||||||
|
|
||||||
|
resolve(combinedCookie);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
request.on("error", (error) => {
|
||||||
|
reject(error);
|
||||||
|
});
|
||||||
|
|
||||||
|
request.write(postData);
|
||||||
|
request.end();
|
||||||
|
});
|
||||||
|
|
||||||
|
return finalCookie;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function makeInquiryRequest(info, type, cookie) {
|
||||||
|
const payloadData =
|
||||||
|
type === "person"
|
||||||
|
? querystring.stringify({
|
||||||
|
nationalCode: info,
|
||||||
|
birthDateString: "1404/08/12",
|
||||||
|
})
|
||||||
|
: type === "unit"
|
||||||
|
? querystring.stringify({
|
||||||
|
NationalCode: info,
|
||||||
|
})
|
||||||
|
: JSON.stringify({
|
||||||
|
NationaId: info,
|
||||||
|
});
|
||||||
|
|
||||||
|
const requestOptions = {
|
||||||
|
hostname: "ba124.ir",
|
||||||
|
path:
|
||||||
|
type === "person"
|
||||||
|
? "/Inquiries/PersonInfo"
|
||||||
|
: type === "unit"
|
||||||
|
? "/Inquiries/CallGetLegalPersonInfoByNationalCode"
|
||||||
|
: "/Inquiries/AsnafGWLicenseInquiry",
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-Type":
|
||||||
|
type === "person" || type === "unit"
|
||||||
|
? "application/x-www-form-urlencoded; charset=UTF-8"
|
||||||
|
: "application/json; charset=UTF-8",
|
||||||
|
"Content-Length": Buffer.byteLength(payloadData),
|
||||||
|
"User-Agent":
|
||||||
|
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36",
|
||||||
|
Accept: "application/json, text/javascript, */*; q=0.01",
|
||||||
|
Accept_Encoding: "gzip, deflate, br, zstd",
|
||||||
|
Accept_Language: "en-US,en;q=0.9,fa-IR;q=0.8,fa;q=0.7",
|
||||||
|
Connection: "keep-alive",
|
||||||
|
Cookie: cookie,
|
||||||
|
Host: "ba124.ir",
|
||||||
|
Origin: "https://ba124.ir",
|
||||||
|
Referer:
|
||||||
|
type === "person"
|
||||||
|
? "https://ba124.ir/Inquiries/PersonInfo"
|
||||||
|
: type === "unit"
|
||||||
|
? "https://ba124.ir/Inquiries/GetLegalPersonInfoByNationalCode"
|
||||||
|
: "https://ba124.ir/Inquiries/AsnafGWLicenseInquiry",
|
||||||
|
"Sec-Ch-Ua":
|
||||||
|
'"Chromium";v="142", "Google Chrome";v="142", "Not_A Brand";v="99"',
|
||||||
|
"Sec-Ch-Ua-Mobile": "?0",
|
||||||
|
"Sec-Ch-Ua-Platform": '"Windows"',
|
||||||
|
"Sec-Fetch-Dest": "empty",
|
||||||
|
"Sec-Fetch-Mode": "cors",
|
||||||
|
"Sec-Fetch-Site": "same-origin",
|
||||||
|
"X-Requested-With": "XMLHttpRequest",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const finalInfo = await new Promise((resolve, reject) => {
|
||||||
|
const request = https.request(requestOptions, (response) => {
|
||||||
|
const chunks = [];
|
||||||
|
|
||||||
|
response.on("data", (chunk) => {
|
||||||
|
chunks.push(chunk);
|
||||||
|
});
|
||||||
|
|
||||||
|
response.on("end", () => {
|
||||||
|
try {
|
||||||
|
const raw = Buffer.concat(chunks);
|
||||||
|
const jsonData = parseBaJsonResponse(response, raw);
|
||||||
|
resolve(jsonData);
|
||||||
|
} catch (error) {
|
||||||
|
reject(new Error(`Invalid JSON response: ${error.message}`));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
request.on("error", (error) => {
|
||||||
|
reject(error);
|
||||||
|
});
|
||||||
|
|
||||||
|
request.write(payloadData);
|
||||||
|
request.end();
|
||||||
|
});
|
||||||
|
|
||||||
|
return finalInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function makeLadingRequest(start, end, postal, cookie) {
|
||||||
|
const payloadData = JSON.stringify({
|
||||||
|
FromIssuDate: start,
|
||||||
|
ToIssuDate: end,
|
||||||
|
CodePosti: postal,
|
||||||
|
MabdaYaMaghsad: 3,
|
||||||
|
});
|
||||||
|
|
||||||
|
const requestOptions = {
|
||||||
|
hostname: "ba124.ir",
|
||||||
|
path: "/Inquiries/CallGetBarnamehInfoByCodePosti",
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json; charset=UTF-8",
|
||||||
|
"Content-Length": Buffer.byteLength(payloadData),
|
||||||
|
"User-Agent":
|
||||||
|
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36",
|
||||||
|
Accept: "application/json, text/javascript, */*; q=0.01",
|
||||||
|
Accept_Encoding: "gzip, deflate, br, zstd",
|
||||||
|
Accept_Language:
|
||||||
|
"en-US,en;q=0.9,fa-IR;q=0.8,fa;q=0.7,ar-AE;q=0.6,ar;q=0.5,en-GB;q=0.4",
|
||||||
|
Connection: "keep-alive",
|
||||||
|
Cookie: cookie,
|
||||||
|
Host: "ba124.ir",
|
||||||
|
Origin: "https://ba124.ir",
|
||||||
|
Referer: "https://ba124.ir/Inquiries/GetBarnamehInfoByCodePosti",
|
||||||
|
"Sec-Ch-Ua":
|
||||||
|
'"Chromium";v="142", "Google Chrome";v="142", "Not_A Brand";v="99"',
|
||||||
|
"Sec-Ch-Ua-Mobile": "?0",
|
||||||
|
"Sec-Ch-Ua-Platform": '"Linux"',
|
||||||
|
"Sec-Fetch-Dest": "empty",
|
||||||
|
"Sec-Fetch-Mode": "cors",
|
||||||
|
"Sec-Fetch-Site": "same-origin",
|
||||||
|
"X-Requested-With": "XMLHttpRequest",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const finalInfo = await new Promise((resolve, reject) => {
|
||||||
|
const request = https.request(requestOptions, (response) => {
|
||||||
|
const chunks = [];
|
||||||
|
|
||||||
|
response.on("data", (chunk) => {
|
||||||
|
chunks.push(chunk);
|
||||||
|
});
|
||||||
|
|
||||||
|
response.on("end", () => {
|
||||||
|
try {
|
||||||
|
const raw = Buffer.concat(chunks);
|
||||||
|
const jsonData = parseBaJsonResponse(response, raw);
|
||||||
|
resolve(jsonData);
|
||||||
|
} catch (error) {
|
||||||
|
reject(new Error(`Invalid JSON response: ${error.message}`));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
request.on("error", (error) => {
|
||||||
|
reject(error);
|
||||||
|
});
|
||||||
|
|
||||||
|
request.write(payloadData);
|
||||||
|
request.end();
|
||||||
|
});
|
||||||
|
|
||||||
|
return finalInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function makeVeterinaryTransferRequest(trIDCode, cookie) {
|
||||||
|
const payloadData = querystring.stringify({
|
||||||
|
trIDCode,
|
||||||
|
});
|
||||||
|
|
||||||
|
const requestOptions = {
|
||||||
|
hostname: "ba124.ir",
|
||||||
|
path: "/Inquiries/CallVeterinaryTransfer",
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
|
||||||
|
"Content-Length": Buffer.byteLength(payloadData),
|
||||||
|
"User-Agent":
|
||||||
|
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36",
|
||||||
|
Accept: "application/json, text/javascript, */*; q=0.01",
|
||||||
|
"Accept-Encoding": "gzip, deflate, br",
|
||||||
|
"Accept-Language":
|
||||||
|
"en-US,en;q=0.9,fa-IR;q=0.8,fa;q=0.7,ar-AE;q=0.6,ar;q=0.5,en-GB;q=0.4",
|
||||||
|
Connection: "keep-alive",
|
||||||
|
Cookie: cookie,
|
||||||
|
Host: "ba124.ir",
|
||||||
|
Origin: "https://ba124.ir",
|
||||||
|
Referer: "https://ba124.ir/Inquiries/VeterinaryTransfer",
|
||||||
|
"Sec-Ch-Ua":
|
||||||
|
'"Chromium";v="142", "Google Chrome";v="142", "Not_A Brand";v="99"',
|
||||||
|
"Sec-Ch-Ua-Mobile": "?0",
|
||||||
|
"Sec-Ch-Ua-Platform": '"Linux"',
|
||||||
|
"Sec-Fetch-Dest": "empty",
|
||||||
|
"Sec-Fetch-Mode": "cors",
|
||||||
|
"Sec-Fetch-Site": "same-origin",
|
||||||
|
"X-Requested-With": "XMLHttpRequest",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const finalInfo = await new Promise((resolve, reject) => {
|
||||||
|
const request = https.request(requestOptions, (response) => {
|
||||||
|
const chunks = [];
|
||||||
|
|
||||||
|
response.on("data", (chunk) => {
|
||||||
|
chunks.push(chunk);
|
||||||
|
});
|
||||||
|
|
||||||
|
response.on("end", () => {
|
||||||
|
try {
|
||||||
|
const raw = Buffer.concat(chunks);
|
||||||
|
const jsonData = parseBaJsonResponse(response, raw);
|
||||||
|
resolve(jsonData);
|
||||||
|
} catch (error) {
|
||||||
|
reject(new Error(`Invalid JSON response: ${error.message}`));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
request.on("error", (error) => {
|
||||||
|
reject(error);
|
||||||
|
});
|
||||||
|
|
||||||
|
request.write(payloadData);
|
||||||
|
request.end();
|
||||||
|
});
|
||||||
|
|
||||||
|
return finalInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function makeAgriWindowsUnitsRequest(PartIdCode, cookie) {
|
||||||
|
const payloadData = querystring.stringify({
|
||||||
|
PartIdCode,
|
||||||
|
});
|
||||||
|
|
||||||
|
const requestOptions = {
|
||||||
|
hostname: "ba124.ir",
|
||||||
|
path: "/Inquiries/CallAgriWindowsUnits",
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
|
||||||
|
"Content-Length": Buffer.byteLength(payloadData),
|
||||||
|
"User-Agent":
|
||||||
|
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36",
|
||||||
|
Accept: "application/json, text/javascript, */*; q=0.01",
|
||||||
|
"Accept-Encoding": "gzip, deflate, br",
|
||||||
|
"Accept-Language":
|
||||||
|
"en-US,en;q=0.9,fa-IR;q=0.8,fa;q=0.7,ar-AE;q=0.6,ar;q=0.5,en-GB;q=0.4",
|
||||||
|
Connection: "keep-alive",
|
||||||
|
Cookie: cookie,
|
||||||
|
Host: "ba124.ir",
|
||||||
|
Origin: "https://ba124.ir",
|
||||||
|
Referer: "https://ba124.ir/Inquiries/VeterinaryTransfer",
|
||||||
|
"Sec-Ch-Ua":
|
||||||
|
'"Chromium";v="142", "Google Chrome";v="142", "Not_A Brand";v="99"',
|
||||||
|
"Sec-Ch-Ua-Mobile": "?0",
|
||||||
|
"Sec-Ch-Ua-Platform": '"Linux"',
|
||||||
|
"Sec-Fetch-Dest": "empty",
|
||||||
|
"Sec-Fetch-Mode": "cors",
|
||||||
|
"Sec-Fetch-Site": "same-origin",
|
||||||
|
"X-Requested-With": "XMLHttpRequest",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const finalInfo = await new Promise((resolve, reject) => {
|
||||||
|
const request = https.request(requestOptions, (response) => {
|
||||||
|
const chunks = [];
|
||||||
|
|
||||||
|
response.on("data", (chunk) => {
|
||||||
|
chunks.push(chunk);
|
||||||
|
});
|
||||||
|
|
||||||
|
response.on("end", () => {
|
||||||
|
try {
|
||||||
|
const raw = Buffer.concat(chunks);
|
||||||
|
const jsonData = parseBaJsonResponse(response, raw);
|
||||||
|
resolve(jsonData);
|
||||||
|
} catch (error) {
|
||||||
|
reject(new Error(`Invalid JSON response: ${error.message}`));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
request.on("error", (error) => {
|
||||||
|
reject(error);
|
||||||
|
});
|
||||||
|
|
||||||
|
request.write(payloadData);
|
||||||
|
request.end();
|
||||||
|
});
|
||||||
|
|
||||||
|
return finalInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
router.use(verifyToken);
|
||||||
|
|
||||||
|
router.get("/national-documents", async (req, res) => {
|
||||||
|
const { info, type } = req.query;
|
||||||
|
|
||||||
|
if (!info) {
|
||||||
|
return res.status(400).json({
|
||||||
|
error: "Missing required field: info",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
let finalCookie = await performLogin();
|
||||||
|
let finalInfo = await makeInquiryRequest(info, type, finalCookie);
|
||||||
|
|
||||||
|
while (finalInfo && finalInfo.error) {
|
||||||
|
console.log("Session expired, retrying login and request...");
|
||||||
|
finalCookie = await performLogin();
|
||||||
|
finalInfo = await makeInquiryRequest(info, type, finalCookie);
|
||||||
|
}
|
||||||
|
|
||||||
|
res.json(finalInfo);
|
||||||
|
} catch (error) {
|
||||||
|
res.status(500).json({
|
||||||
|
error: "Failed to fetch person info",
|
||||||
|
message: error.message,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
router.get("/ladinginfo", async (req, res) => {
|
||||||
|
const { start, end, postal } = req.query;
|
||||||
|
|
||||||
|
if (!start || !end || !postal) {
|
||||||
|
return res.status(400).json({
|
||||||
|
error: "Missing required fields: start, end, and postal are required",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
let finalCookie = await performLogin();
|
||||||
|
let finalInfo = await makeLadingRequest(start, end, postal, finalCookie);
|
||||||
|
|
||||||
|
while (finalInfo && finalInfo.error) {
|
||||||
|
console.log("Session expired, retrying login and request...");
|
||||||
|
finalCookie = await performLogin();
|
||||||
|
finalInfo = await makeLadingRequest(start, end, postal, finalCookie);
|
||||||
|
}
|
||||||
|
|
||||||
|
res.json(finalInfo);
|
||||||
|
} catch (error) {
|
||||||
|
res.status(500).json({
|
||||||
|
error: "Failed to fetch lading info",
|
||||||
|
message: error.message,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
router.get("/veterinary-transfer", async (req, res) => {
|
||||||
|
const { trIDCode } = req.query;
|
||||||
|
|
||||||
|
if (!trIDCode) {
|
||||||
|
return res.status(400).json({
|
||||||
|
error: "Missing required field: trIDCode",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
let finalCookie = await performLogin();
|
||||||
|
let finalInfo = await makeVeterinaryTransferRequest(trIDCode, finalCookie);
|
||||||
|
|
||||||
|
while (finalInfo && finalInfo.error) {
|
||||||
|
console.log("Session expired, retrying login and request...");
|
||||||
|
finalCookie = await performLogin();
|
||||||
|
finalInfo = await makeVeterinaryTransferRequest(trIDCode, finalCookie);
|
||||||
|
}
|
||||||
|
|
||||||
|
res.json(finalInfo);
|
||||||
|
} catch (error) {
|
||||||
|
res.status(500).json({
|
||||||
|
error: "Failed to fetch veterinary transfer info",
|
||||||
|
message: error.message,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
router.get("/inquiry-farm", async (req, res) => {
|
||||||
|
const { PartIdCode } = req.query;
|
||||||
|
|
||||||
|
if (!PartIdCode) {
|
||||||
|
return res.status(400).json({
|
||||||
|
error: "Missing required field: PartIdCode",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
let finalCookie = await performLogin();
|
||||||
|
let finalInfo = await makeAgriWindowsUnitsRequest(PartIdCode, finalCookie);
|
||||||
|
|
||||||
|
while (finalInfo && finalInfo.error) {
|
||||||
|
console.log("Session expired, retrying login and request...");
|
||||||
|
finalCookie = await performLogin();
|
||||||
|
finalInfo = await makeAgriWindowsUnitsRequest(PartIdCode, finalCookie);
|
||||||
|
}
|
||||||
|
|
||||||
|
res.json(finalInfo);
|
||||||
|
} catch (error) {
|
||||||
|
res.status(500).json({
|
||||||
|
error: "Failed to fetch inquiry farm info",
|
||||||
|
message: error.message,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = router;
|
||||||
359
routes/peopleInfoRoutes.js
Normal file
359
routes/peopleInfoRoutes.js
Normal file
@@ -0,0 +1,359 @@
|
|||||||
|
const express = require("express");
|
||||||
|
const router = express.Router();
|
||||||
|
const PeopleInfo = require("../models/peopleInfo");
|
||||||
|
|
||||||
|
router.get("/people_info", async (req, res) => {
|
||||||
|
try {
|
||||||
|
const { searchfield, value } = req.query;
|
||||||
|
|
||||||
|
if (!searchfield || !value) {
|
||||||
|
return res.status(400).json({
|
||||||
|
message: "searchfield and value parameters are required",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
let matchQuery = {};
|
||||||
|
|
||||||
|
if (searchfield === "mobile") {
|
||||||
|
let normalizedSearch = value.replace(/\D/g, "");
|
||||||
|
|
||||||
|
const withLeadingZero = normalizedSearch.startsWith("0")
|
||||||
|
? normalizedSearch
|
||||||
|
: `0${normalizedSearch}`;
|
||||||
|
const withoutLeadingZero = normalizedSearch.startsWith("0")
|
||||||
|
? normalizedSearch.substring(1)
|
||||||
|
: normalizedSearch;
|
||||||
|
|
||||||
|
const numericValue = parseInt(withoutLeadingZero, 10);
|
||||||
|
|
||||||
|
matchQuery = {
|
||||||
|
$or: [
|
||||||
|
{ mobile: withLeadingZero },
|
||||||
|
{ mobile: withoutLeadingZero },
|
||||||
|
{ mobile: numericValue },
|
||||||
|
],
|
||||||
|
};
|
||||||
|
} else if (searchfield === "name") {
|
||||||
|
matchQuery = {
|
||||||
|
$or: [
|
||||||
|
{ name: { $regex: value, $options: "i" } },
|
||||||
|
{ family: { $regex: value, $options: "i" } },
|
||||||
|
{
|
||||||
|
$expr: {
|
||||||
|
$regexMatch: {
|
||||||
|
input: { $concat: ["$name", " ", "$family"] },
|
||||||
|
regex: value,
|
||||||
|
options: "i",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
} else if (searchfield === "nationalcode") {
|
||||||
|
matchQuery = { nationalcode: value };
|
||||||
|
} else {
|
||||||
|
return res.status(400).json({
|
||||||
|
message:
|
||||||
|
"Invalid searchfield. Must be 'mobile', 'name', or 'nationalcode'",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const pipeline = [
|
||||||
|
{ $match: matchQuery },
|
||||||
|
|
||||||
|
{ $limit: 10000 },
|
||||||
|
|
||||||
|
{
|
||||||
|
$group: {
|
||||||
|
_id: "$nationalcode",
|
||||||
|
items: {
|
||||||
|
$push: {
|
||||||
|
name: "$name",
|
||||||
|
family: "$family",
|
||||||
|
mobile: "$mobile",
|
||||||
|
mellicard: "$mellicard",
|
||||||
|
mellatcard: "$mellatcard",
|
||||||
|
father: "$father",
|
||||||
|
birthdate: "$birthdate",
|
||||||
|
info1: "$info1",
|
||||||
|
info2: "$info2",
|
||||||
|
info3: "$info3",
|
||||||
|
info4: "$info4",
|
||||||
|
hasMellatcard: {
|
||||||
|
$cond: [{ $ne: ["$mellatcard", null] }, true, false],
|
||||||
|
},
|
||||||
|
hasMellicard: {
|
||||||
|
$cond: [{ $ne: ["$mellicard", null] }, true, false],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
$project: {
|
||||||
|
nationalcode: "$_id",
|
||||||
|
items: 1,
|
||||||
|
|
||||||
|
firstWithMellatcard: {
|
||||||
|
$arrayElemAt: [
|
||||||
|
{
|
||||||
|
$filter: {
|
||||||
|
input: "$items",
|
||||||
|
as: "item",
|
||||||
|
cond: { $eq: ["$$item.hasMellatcard", true] },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
0,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
firstWithMellicard: {
|
||||||
|
$arrayElemAt: [
|
||||||
|
{
|
||||||
|
$filter: {
|
||||||
|
input: "$items",
|
||||||
|
as: "item",
|
||||||
|
cond: { $eq: ["$$item.hasMellicard", true] },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
0,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
hasAnyMellatcard: {
|
||||||
|
$gt: [
|
||||||
|
{
|
||||||
|
$size: {
|
||||||
|
$filter: {
|
||||||
|
input: "$items",
|
||||||
|
as: "item",
|
||||||
|
cond: { $eq: ["$$item.hasMellatcard", true] },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
0,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
hasAnyMellicard: {
|
||||||
|
$gt: [
|
||||||
|
{
|
||||||
|
$size: {
|
||||||
|
$filter: {
|
||||||
|
input: "$items",
|
||||||
|
as: "item",
|
||||||
|
cond: { $eq: ["$$item.hasMellicard", true] },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
0,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
$project: {
|
||||||
|
nationalcode: 1,
|
||||||
|
name: {
|
||||||
|
$cond: [
|
||||||
|
{ $ne: ["$firstWithMellatcard", null] },
|
||||||
|
"$firstWithMellatcard.name",
|
||||||
|
{
|
||||||
|
$cond: [
|
||||||
|
{ $ne: ["$firstWithMellicard", null] },
|
||||||
|
"$firstWithMellicard.name",
|
||||||
|
{ $arrayElemAt: ["$items.name", 0] },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
family: {
|
||||||
|
$cond: [
|
||||||
|
{ $ne: ["$firstWithMellatcard", null] },
|
||||||
|
"$firstWithMellatcard.family",
|
||||||
|
{
|
||||||
|
$cond: [
|
||||||
|
{ $ne: ["$firstWithMellicard", null] },
|
||||||
|
"$firstWithMellicard.family",
|
||||||
|
{ $arrayElemAt: ["$items.family", 0] },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
father: {
|
||||||
|
$cond: [
|
||||||
|
{ $ne: ["$firstWithMellatcard", null] },
|
||||||
|
"$firstWithMellatcard.father",
|
||||||
|
{
|
||||||
|
$cond: [
|
||||||
|
{ $ne: ["$firstWithMellicard", null] },
|
||||||
|
"$firstWithMellicard.father",
|
||||||
|
null,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
birthdate: {
|
||||||
|
$cond: [
|
||||||
|
{ $ne: ["$firstWithMellatcard", null] },
|
||||||
|
"$firstWithMellatcard.birthdate",
|
||||||
|
{
|
||||||
|
$cond: [
|
||||||
|
{ $ne: ["$firstWithMellicard", null] },
|
||||||
|
"$firstWithMellicard.birthdate",
|
||||||
|
null,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
mobile: {
|
||||||
|
$filter: {
|
||||||
|
input: "$items.mobile",
|
||||||
|
as: "mob",
|
||||||
|
cond: { $ne: ["$$mob", null] },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
allCards: {
|
||||||
|
$reduce: {
|
||||||
|
input: "$items",
|
||||||
|
initialValue: [],
|
||||||
|
in: {
|
||||||
|
$concatArrays: [
|
||||||
|
"$$value",
|
||||||
|
{
|
||||||
|
$filter: {
|
||||||
|
input: ["$$this.mellatcard", "$$this.mellicard"],
|
||||||
|
as: "card",
|
||||||
|
cond: { $ne: ["$$card", null] },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
info: {
|
||||||
|
$reduce: {
|
||||||
|
input: "$items",
|
||||||
|
initialValue: [],
|
||||||
|
in: {
|
||||||
|
$concatArrays: [
|
||||||
|
"$$value",
|
||||||
|
{
|
||||||
|
$filter: {
|
||||||
|
input: [
|
||||||
|
"$$this.info1",
|
||||||
|
"$$this.info2",
|
||||||
|
"$$this.info3",
|
||||||
|
"$$this.info4",
|
||||||
|
],
|
||||||
|
as: "inf",
|
||||||
|
cond: { $ne: ["$$inf", null] },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
$project: {
|
||||||
|
nationalcode: 1,
|
||||||
|
name: 1,
|
||||||
|
family: 1,
|
||||||
|
father: 1,
|
||||||
|
birthdate: 1,
|
||||||
|
mobile: 1,
|
||||||
|
card: "$allCards",
|
||||||
|
info: 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const results = await PeopleInfo.aggregate(pipeline).allowDiskUse(true);
|
||||||
|
|
||||||
|
const processedResults = results.map((result) => {
|
||||||
|
const mobileSet = new Set();
|
||||||
|
result.mobile.forEach((mob) => {
|
||||||
|
if (mob == null) return;
|
||||||
|
const mobStr = String(mob);
|
||||||
|
const normalized = mobStr.startsWith("0")
|
||||||
|
? mobStr.substring(1)
|
||||||
|
: mobStr;
|
||||||
|
mobileSet.add(`0${normalized}`);
|
||||||
|
});
|
||||||
|
result.mobile = Array.from(mobileSet);
|
||||||
|
|
||||||
|
if (result.card) {
|
||||||
|
const cardSet = new Set();
|
||||||
|
result.card.forEach((card) => {
|
||||||
|
if (card && typeof card === "string") {
|
||||||
|
cardSet.add(card.trim());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
result.card = Array.from(cardSet);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.birthdate && result.birthdate instanceof Date) {
|
||||||
|
result.birthdate = result.birthdate.toISOString().split("T")[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
result.info = result.info.map((inf) => {
|
||||||
|
return typeof inf === "string" ? inf.replace(/\t/g, "") : inf;
|
||||||
|
});
|
||||||
|
|
||||||
|
return result;
|
||||||
|
});
|
||||||
|
|
||||||
|
res.status(200).json({
|
||||||
|
data: processedResults,
|
||||||
|
count: processedResults.length,
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error fetching people info:", error);
|
||||||
|
res
|
||||||
|
.status(500)
|
||||||
|
.json({ message: "Internal Server Error", error: error.message });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
router.post("/people_info", async (req, res) => {
|
||||||
|
try {
|
||||||
|
const {
|
||||||
|
first_name,
|
||||||
|
last_name,
|
||||||
|
mobile,
|
||||||
|
postal,
|
||||||
|
province,
|
||||||
|
city,
|
||||||
|
nationalcode,
|
||||||
|
} = req.body;
|
||||||
|
|
||||||
|
const newPeopleInfo = new PeopleInfo({
|
||||||
|
first_name,
|
||||||
|
last_name,
|
||||||
|
mobile,
|
||||||
|
postal,
|
||||||
|
province,
|
||||||
|
city,
|
||||||
|
nationalcode,
|
||||||
|
});
|
||||||
|
|
||||||
|
await newPeopleInfo.save();
|
||||||
|
|
||||||
|
res.status(201).json({
|
||||||
|
message: "People info created successfully",
|
||||||
|
data: newPeopleInfo,
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error creating people info:", error);
|
||||||
|
res
|
||||||
|
.status(500)
|
||||||
|
.json({ message: "Internal Server Error", error: error.message });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = router;
|
||||||
159
routes/placeRoutes.js
Normal file
159
routes/placeRoutes.js
Normal file
@@ -0,0 +1,159 @@
|
|||||||
|
const express = require("express");
|
||||||
|
const router = express.Router();
|
||||||
|
const Place = require("../models/place");
|
||||||
|
const UpdateData = require("../models/UpdateData");
|
||||||
|
const { verifyToken } = require("../lib/jwtUtils");
|
||||||
|
|
||||||
|
router.use(verifyToken);
|
||||||
|
router.post("/place", async (req, res) => {
|
||||||
|
try {
|
||||||
|
const { name, description, location, category } = req.body;
|
||||||
|
const newPlace = new Place({ name, description, location, category });
|
||||||
|
await newPlace.save();
|
||||||
|
|
||||||
|
res
|
||||||
|
.status(201)
|
||||||
|
.json({ message: "Place created successfully", place: newPlace });
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error creating place:", error);
|
||||||
|
res.status(500).json({ message: "Internal Server Error" });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
router.get("/place_data/:placeId", async (req, res) => {
|
||||||
|
try {
|
||||||
|
const placeId = req.params.placeId;
|
||||||
|
const place = await Place.findById(placeId);
|
||||||
|
|
||||||
|
if (!place) {
|
||||||
|
return res.status(404).json({ message: "Place not found" });
|
||||||
|
}
|
||||||
|
|
||||||
|
res.status(200).json({ place });
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error retrieving place:", error);
|
||||||
|
res.status(500).json({ message: "Internal Server Error" });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
router.get("/places", async (req, res) => {
|
||||||
|
try {
|
||||||
|
const places = await Place.find();
|
||||||
|
|
||||||
|
res.status(200).json(places);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error retrieving places:", error);
|
||||||
|
res.status(500).json({ message: "Internal Server Error" });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
router.delete("/places/:placeId", async (req, res) => {
|
||||||
|
try {
|
||||||
|
const placeId = req.params.placeId;
|
||||||
|
|
||||||
|
const deletedPlace = await Place.findByIdAndDelete(placeId);
|
||||||
|
|
||||||
|
if (!deletedPlace) {
|
||||||
|
return res.status(404).json({ message: "Place not found" });
|
||||||
|
}
|
||||||
|
|
||||||
|
res
|
||||||
|
.status(200)
|
||||||
|
.json({ message: "Place deleted successfully", place: deletedPlace });
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error deleting place:", error);
|
||||||
|
res.status(500).json({ message: "Internal Server Error" });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
router.put("/places/:placeId", async (req, res) => {
|
||||||
|
try {
|
||||||
|
const placeId = req.params.placeId;
|
||||||
|
const { name, description, location, category } = req.body;
|
||||||
|
|
||||||
|
const updatedPlace = await Place.findByIdAndUpdate(
|
||||||
|
placeId,
|
||||||
|
{ name, description, location, category },
|
||||||
|
{ new: true } // Set { new: true } to return the updated document
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!updatedPlace) {
|
||||||
|
return res.status(404).json({ message: "Place not found" });
|
||||||
|
}
|
||||||
|
|
||||||
|
res
|
||||||
|
.status(200)
|
||||||
|
.json({ message: "Place updated successfully", place: updatedPlace });
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error updating place:", error);
|
||||||
|
res.status(500).json({ message: "Internal Server Error" });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
router.post("/update-data", async (req, res) => {
|
||||||
|
const { province } = req.body;
|
||||||
|
|
||||||
|
if (!province) {
|
||||||
|
return res.status(400).send("Province is required");
|
||||||
|
}
|
||||||
|
|
||||||
|
let api = `https://pos.rasadyaar.ir/api/report/pos/${province}`;
|
||||||
|
console.log("Fetching data from:", api);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await fetch(api);
|
||||||
|
const newProvinceData = await response.json();
|
||||||
|
|
||||||
|
await UpdateData.updateOne(
|
||||||
|
{},
|
||||||
|
{ $set: { [`records.${province}`]: newProvinceData } },
|
||||||
|
{ upsert: true }
|
||||||
|
);
|
||||||
|
|
||||||
|
res.status(200).send(`Data for ${province} successfully updated!`);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error fetching or updating province data:", error);
|
||||||
|
res.status(500).send("Failed to update data.");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
router.get("/stewards/:key", async (req, res) => {
|
||||||
|
const { key } = req.params;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const data = await UpdateData.findOne();
|
||||||
|
|
||||||
|
if (data && data.records) {
|
||||||
|
const recordData = data.records.get(key);
|
||||||
|
|
||||||
|
if (recordData) {
|
||||||
|
res.status(200).json(recordData);
|
||||||
|
} else {
|
||||||
|
res.status(404).json({ message: `No data found for key: ${key}` });
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
res.status(404).json({ message: "No data found" });
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
res.status(500).json({ message: "Server error" });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
module.exports = router;
|
||||||
|
|
||||||
|
// router
|
||||||
|
// .route("/:id")
|
||||||
|
// .get((req, res) => {
|
||||||
|
// res.send(`User Get ${req.params.id}`);
|
||||||
|
// })
|
||||||
|
// .post((req, res) => {
|
||||||
|
// res.send(`User Get ${req.params.id}`);
|
||||||
|
// })
|
||||||
|
// .put((req, res) => {
|
||||||
|
// res.send(`User Get ${req.params.id}`);
|
||||||
|
// })
|
||||||
|
// .delete((req, res) => {
|
||||||
|
// res.send(`User Get ${req.params.id}`);
|
||||||
|
// });
|
||||||
|
|
||||||
|
// module.exports = router;
|
||||||
161
routes/userRoutes.js
Normal file
161
routes/userRoutes.js
Normal file
@@ -0,0 +1,161 @@
|
|||||||
|
const express = require("express");
|
||||||
|
const router = express.Router();
|
||||||
|
const User = require("../models/user");
|
||||||
|
const jwt = require("jsonwebtoken");
|
||||||
|
const bcrypt = require("bcrypt");
|
||||||
|
const { verifyToken, generateToken } = require("../lib/jwtUtils");
|
||||||
|
|
||||||
|
router.post("/user", async (req, res) => {
|
||||||
|
try {
|
||||||
|
const { mobile, password, fullname, pic, province, permissions, city } =
|
||||||
|
req.body;
|
||||||
|
const hashedPassword = await bcrypt.hash(password, 10);
|
||||||
|
|
||||||
|
const newUser = new User({
|
||||||
|
mobile,
|
||||||
|
password: hashedPassword,
|
||||||
|
pic,
|
||||||
|
fullname,
|
||||||
|
province,
|
||||||
|
city,
|
||||||
|
permissions,
|
||||||
|
});
|
||||||
|
|
||||||
|
await newUser.save();
|
||||||
|
|
||||||
|
const token = generateToken(newUser._id);
|
||||||
|
|
||||||
|
res.status(201).json({
|
||||||
|
message: "User created successfully",
|
||||||
|
user: newUser,
|
||||||
|
token,
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error creating user:", error);
|
||||||
|
res.status(500).json({ message: "Internal Server Error" });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
router.post("/login", async (req, res) => {
|
||||||
|
try {
|
||||||
|
const { mobile, password } = req.body;
|
||||||
|
const user = await User.findOne({ mobile });
|
||||||
|
|
||||||
|
if (!user) {
|
||||||
|
return res.status(403).json({ message: "Invalid credentials" });
|
||||||
|
}
|
||||||
|
|
||||||
|
const passwordMatch = await bcrypt.compare(password, user.password);
|
||||||
|
|
||||||
|
if (!passwordMatch) {
|
||||||
|
return res.status(403).json({ message: "Invalid credentials" });
|
||||||
|
}
|
||||||
|
|
||||||
|
const token = generateToken(user._id);
|
||||||
|
|
||||||
|
const userWithoutPassword = { ...user.toObject() };
|
||||||
|
delete userWithoutPassword.password;
|
||||||
|
|
||||||
|
res
|
||||||
|
.status(200)
|
||||||
|
.json({ message: "Login successful", token, user: userWithoutPassword });
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error during login:", error);
|
||||||
|
res.status(500).json({ message: "Internal Server Error" });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
router.use(verifyToken);
|
||||||
|
|
||||||
|
router.get("/user_profile/:userId", async (req, res) => {
|
||||||
|
try {
|
||||||
|
const userId = req.params.userId;
|
||||||
|
const user = await User.findById(userId);
|
||||||
|
|
||||||
|
if (!user) {
|
||||||
|
return res.status(404).json({ message: "User not found" });
|
||||||
|
}
|
||||||
|
|
||||||
|
res.status(200).json({ user });
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error retrieving user:", error);
|
||||||
|
res.status(500).json({ message: "Internal Server Error" });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
router.get("/users/:province", async (req, res) => {
|
||||||
|
try {
|
||||||
|
const province = req.params.province;
|
||||||
|
|
||||||
|
const users = (await User.find({ province: province })).filter(
|
||||||
|
(item) => !item.permissions.includes("admin")
|
||||||
|
);
|
||||||
|
|
||||||
|
res.status(200).json(users);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error retrieving users:", error);
|
||||||
|
res.status(500).json({ message: "Internal Server Error" });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
router.delete("/users/:userId", async (req, res) => {
|
||||||
|
try {
|
||||||
|
const userId = req.params.userId;
|
||||||
|
|
||||||
|
const deletedUser = await User.findByIdAndDelete(userId);
|
||||||
|
|
||||||
|
if (!deletedUser) {
|
||||||
|
return res.status(404).json({ message: "User not found" });
|
||||||
|
}
|
||||||
|
|
||||||
|
res
|
||||||
|
.status(200)
|
||||||
|
.json({ message: "User deleted successfully", user: deletedUser });
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error deleting user:", error);
|
||||||
|
res.status(500).json({ message: "Internal Server Error" });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
router.put("/user/:userId", async (req, res) => {
|
||||||
|
try {
|
||||||
|
const userId = req.params.userId;
|
||||||
|
const { mobile, password, fullname, pic, province, permissions } = req.body;
|
||||||
|
|
||||||
|
const updatedUser = await User.findByIdAndUpdate(
|
||||||
|
userId,
|
||||||
|
{ mobile, password, fullname, pic, province, permissions },
|
||||||
|
{ new: true } // Set { new: true } to return the updated document
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!updatedUser) {
|
||||||
|
return res.status(404).json({ message: "User not found" });
|
||||||
|
}
|
||||||
|
|
||||||
|
res
|
||||||
|
.status(200)
|
||||||
|
.json({ message: "User updated successfully", user: updatedUser });
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error updating user:", error);
|
||||||
|
res.status(500).json({ message: "Internal Server Error" });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = router;
|
||||||
|
|
||||||
|
// router
|
||||||
|
// .route("/:id")
|
||||||
|
// .get((req, res) => {
|
||||||
|
// res.send(`User Get ${req.params.id}`);
|
||||||
|
// })
|
||||||
|
// .post((req, res) => {
|
||||||
|
// res.send(`User Get ${req.params.id}`);
|
||||||
|
// })
|
||||||
|
// .put((req, res) => {
|
||||||
|
// res.send(`User Get ${req.params.id}`);
|
||||||
|
// })
|
||||||
|
// .delete((req, res) => {
|
||||||
|
// res.send(`User Get ${req.params.id}`);
|
||||||
|
// });
|
||||||
|
|
||||||
|
// module.exports = router;
|
||||||
70
server.js
Normal file
70
server.js
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
require("dotenv").config();
|
||||||
|
const express = require("express");
|
||||||
|
const mongoose = require("mongoose");
|
||||||
|
const cors = require("cors");
|
||||||
|
|
||||||
|
const app = express();
|
||||||
|
|
||||||
|
app.use(express.json());
|
||||||
|
|
||||||
|
const allowedOrigins = [
|
||||||
|
"http://localhost:3000",
|
||||||
|
"http://localhost:3001",
|
||||||
|
"http://localhost:3002",
|
||||||
|
"https://bazres.rasadyar.com/",
|
||||||
|
"https://bazres.rasadyar.net/",
|
||||||
|
"https://bazres.rasadyar.com",
|
||||||
|
"https://bazres.rasadyar.net",
|
||||||
|
"https://ban.rasadyar.com",
|
||||||
|
"https://ban.rasadyar.net",
|
||||||
|
"https://www.ban.rasadyar.com",
|
||||||
|
"https://www.ban.rasadyar.net",
|
||||||
|
];
|
||||||
|
|
||||||
|
app.use(
|
||||||
|
cors({
|
||||||
|
origin: function (origin, callback) {
|
||||||
|
if (!origin) return callback(null, true);
|
||||||
|
if (allowedOrigins.indexOf(origin) !== -1) {
|
||||||
|
callback(null, true);
|
||||||
|
} else {
|
||||||
|
callback(new Error("Not allowed by CORS"));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
credentials: true,
|
||||||
|
allowedHeaders: ["Content-Type", "Authorization"],
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
const PlaceRoutes = require("./routes/placeRoutes");
|
||||||
|
const UserRoutes = require("./routes/userRoutes");
|
||||||
|
const InspectionRoutes = require("./routes/inspectRoutes");
|
||||||
|
const HerdRoutes = require("./routes/herdRoutes");
|
||||||
|
const PeopleInfoRoutes = require("./routes/peopleInfoRoutes");
|
||||||
|
const NationalDocumentsRoutes = require("./routes/nationalDocumentsRoutes");
|
||||||
|
|
||||||
|
app.use("/", PeopleInfoRoutes);
|
||||||
|
|
||||||
|
app.use("/", UserRoutes);
|
||||||
|
app.use("/", HerdRoutes);
|
||||||
|
app.use("/", PlaceRoutes);
|
||||||
|
app.use("/", InspectionRoutes);
|
||||||
|
app.use("/", NationalDocumentsRoutes);
|
||||||
|
|
||||||
|
const uri =
|
||||||
|
process.env.MONGODB_URI ||
|
||||||
|
"mongodb://root:uV6NAvWigykzUK1CR1VJdf4mNbFD0kHjYgZU1lJKgMR0IFTwt1DyCFpKgxwkPeJt@31.7.78.133:14364/default?authSource=admin";
|
||||||
|
|
||||||
|
const mongooseOptions = {};
|
||||||
|
|
||||||
|
mongoose
|
||||||
|
.connect(uri, mongooseOptions)
|
||||||
|
.then(() => {
|
||||||
|
console.log("Connected to MongoDB");
|
||||||
|
|
||||||
|
const PORT = process.env.PORT || 3000;
|
||||||
|
app.listen(PORT, () => {
|
||||||
|
console.log(`Server is running on port ${PORT}`);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch((error) => console.error("Error connecting to MongoDB:", error));
|
||||||
Reference in New Issue
Block a user