Compare commits
12 Commits
779f0707e3
...
eb4ca5919e
| Author | SHA1 | Date | |
|---|---|---|---|
| eb4ca5919e | |||
| 5bf08d04d5 | |||
| e0f7740bc3 | |||
| c554e1750e | |||
| 82256a5d20 | |||
| 798dd80561 | |||
| 7e280ce22f | |||
| 5e2909d4b4 | |||
| 3b1a86f393 | |||
| b1c77ba9c5 | |||
| 1de3d76a9f | |||
| fc5ec6d0bd |
@ -19,3 +19,4 @@ MONGO_CONNECTION_STRING = "mongodb+srv://$DB_USER_NAME:$DB_USER_PASSWORD@$DB_SER
|
||||
|
||||
JWT_SECRET_AUTH = ""
|
||||
JWT_SECRET_SHARED_REPORT = ""
|
||||
JWT_EXPIRATION_TIME = "365d"
|
||||
@ -2,12 +2,23 @@ const crypto = require('crypto');
|
||||
const fetch = require('node-fetch');
|
||||
const Vehicle = require('../models/vehicle');
|
||||
const DebugInfo = require('../models/DebugInfo');
|
||||
const Centrifuge = require('centrifuge');
|
||||
const { Centrifuge } = require('centrifuge');
|
||||
const SockJS = require('sockjs-client');
|
||||
const WebSocket = require('ws');
|
||||
|
||||
const baseUrl = 'https://avtocod.ru/api/v3';
|
||||
const tokenRefreshUrl = 'https://avtocod.ru/api/centrifuge/refresh';
|
||||
|
||||
let deviceToken = crypto.createHash('sha256').update(Date.now().toString()).digest().toString('hex');
|
||||
|
||||
const myWs = function (options) {
|
||||
return class wsClass extends WebSocket {
|
||||
constructor(...args) {
|
||||
super(...[...args, ...[options]])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function fromBase64(data) {
|
||||
return Buffer.from(data, 'base64').toString('binary');
|
||||
}
|
||||
@ -37,10 +48,47 @@ function decryptReport(report, hash) {
|
||||
return JSON.parse(decrypted.toString());
|
||||
}
|
||||
|
||||
function getToken(ctx) {
|
||||
console.log('+++++ getToken');
|
||||
return new Promise((resolve, reject) => {
|
||||
fetch(tokenRefreshUrl, {
|
||||
method: 'POST',
|
||||
headers: new Headers({ 'Content-Type': 'application/json' }),
|
||||
body: JSON.stringify(ctx)
|
||||
})
|
||||
.then(res => {
|
||||
if (!res.ok) {
|
||||
throw new Error(`Unexpected status code ${res.status}`);
|
||||
}
|
||||
return res.json();
|
||||
})
|
||||
.then(data => {
|
||||
resolve(data.token);
|
||||
})
|
||||
.catch(err => {
|
||||
reject(err);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function waitForReport(centrifugoConfig, channel) {
|
||||
return new Promise((resolve, reject) => {
|
||||
|
||||
let report = null;
|
||||
let centrifuge = new Centrifuge(centrifugoConfig.uri, { sockjs: SockJS });
|
||||
let centrifuge = new Centrifuge([{
|
||||
transport: 'websocket',
|
||||
endpoint: centrifugoConfig.uri
|
||||
}], {
|
||||
websocket: myWs({ headers: {
|
||||
'Sec-Fetch-Site': 'same-site',
|
||||
'Sec-Fetch-Mode': 'websocket',
|
||||
'Sec-Fetch-Dest': 'websocket',
|
||||
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:109.0) Gecko/20100101 Firefox/109.0'
|
||||
} }),
|
||||
token: centrifugoConfig.token,
|
||||
getToken: getToken,
|
||||
debug: false
|
||||
});
|
||||
|
||||
let timeout = setTimeout(() => {
|
||||
centrifuge.disconnect();
|
||||
@ -51,7 +99,9 @@ function waitForReport(centrifugoConfig, channel) {
|
||||
}
|
||||
}, 10000);
|
||||
|
||||
centrifuge.subscribe(channel, message => {
|
||||
const sub = centrifuge.newSubscription(channel);
|
||||
|
||||
sub.on('publication', function(message) {
|
||||
if(message.data.event == 'report-ready') {
|
||||
clearTimeout(timeout);
|
||||
centrifuge.disconnect();
|
||||
@ -61,7 +111,7 @@ function waitForReport(centrifugoConfig, channel) {
|
||||
}
|
||||
});
|
||||
|
||||
centrifuge.setToken(centrifugoConfig.token);
|
||||
sub.subscribe();
|
||||
centrifuge.connect();
|
||||
});
|
||||
}
|
||||
@ -73,6 +123,7 @@ class AvtocodProvider {
|
||||
let resp = await getJson(url);
|
||||
|
||||
let html = await getPage(resp.report_uri);
|
||||
|
||||
let result = html.match(/<meta name="app-version-hash" content="(.*?)" \/>/);
|
||||
if(result == null) {
|
||||
throw Error('Error getting api version hash');
|
||||
|
||||
@ -16,6 +16,7 @@ module.exports = function (options) {
|
||||
jsonwebtoken.verify(token, options.secret, (error, decoded) => {
|
||||
if(error) {
|
||||
res.status(401).send({ success: false, error: error.message });
|
||||
console.error(error);
|
||||
} else {
|
||||
req.user = decoded;
|
||||
next();
|
||||
@ -23,12 +24,15 @@ module.exports = function (options) {
|
||||
});
|
||||
} else {
|
||||
res.status(401).send({ success: false, error: 'Unsupported authorization header' });
|
||||
console.error('Unsupported authorization header');
|
||||
}
|
||||
} else {
|
||||
res.status(401).send({ success: false, error: 'Invalid authorization header' });
|
||||
console.error('Invalid authorization header');
|
||||
}
|
||||
} else {
|
||||
res.status(401).send({ success: false, error: 'Missing authorization header' });
|
||||
console.error('Missing authorization header');
|
||||
}
|
||||
};
|
||||
};
|
||||
@ -14,7 +14,7 @@ module.exports = function (uri) {
|
||||
|
||||
connection
|
||||
.then(function (client) {
|
||||
req['db'] = client.db('autocatdev');
|
||||
req['db'] = client.db('autocat');
|
||||
next();
|
||||
})
|
||||
.catch(function (err) {
|
||||
|
||||
15
migration.js
15
migration.js
@ -51,9 +51,22 @@ async function fixNullEvents() {
|
||||
}
|
||||
}
|
||||
|
||||
async function fixNullNotes() {
|
||||
let client = await MongoClient.connect(process.env.MONGO_CONNECTION_STRING, { useUnifiedTopology: true });
|
||||
let db = client.db('autocatdev');
|
||||
let collection = db.collection('vehicles');
|
||||
let vehicles = await collection.find().toArray();
|
||||
for(let vehicle of vehicles) {
|
||||
if(vehicle.notes == null) {
|
||||
//console.log(vehicle.events);
|
||||
await collection.updateOne({ number: vehicle.number }, { $set: { notes: [] } });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
(async () => {
|
||||
//await addUpdatedDate();
|
||||
//await addDebugInfoStatus();
|
||||
await fixNullEvents();
|
||||
await fixNullNotes();
|
||||
console.log('====== Done ======');
|
||||
})();
|
||||
|
||||
@ -35,8 +35,8 @@ class Vehicle {
|
||||
|
||||
let v = new Vehicle();
|
||||
v.brand = { name: tech.brand.name, logo: tech.brand?.logotype?.uri };
|
||||
v.category = report.fields.additional_info.vehicle.category.code;
|
||||
v.engine = { number: e.number, volume: e.volume, powerHp: e.power.hp, powerKw: e.power.kw, fuelType: e.fuel?.type };
|
||||
v.category = report.fields.additional_info?.vehicle.category.code;
|
||||
v.engine = { number: e.number, volume: e.volume, powerHp: e.power?.hp, powerKw: e.power?.kw, fuelType: e.fuel?.type };
|
||||
v.model = tech.model ? { name: tech.model.name } : null;
|
||||
v.year = tech.year;
|
||||
v.number = report.identifiers_query.query;
|
||||
|
||||
5788
package-lock.json
generated
5788
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -13,7 +13,7 @@
|
||||
"dependencies": {
|
||||
"abort-controller": "^3.0.0",
|
||||
"body-parser": "^1.19.0",
|
||||
"centrifuge": "^2.8.3",
|
||||
"centrifuge": "^3.1.0",
|
||||
"compress": "^0.99.0",
|
||||
"compression": "^1.7.4",
|
||||
"cors": "^2.8.5",
|
||||
@ -22,13 +22,14 @@
|
||||
"express": "^4.17.1",
|
||||
"express-bearer-token": "^2.4.0",
|
||||
"jsonwebtoken": "^8.5.1",
|
||||
"mongodb": "^3.6.1",
|
||||
"mongodb": "^4.13.0",
|
||||
"node-fetch": "^2.6.1",
|
||||
"node-html-parser": "^2.0.0",
|
||||
"response-time": "^2.3.2",
|
||||
"sockjs-client": "^1.5.2",
|
||||
"utf8": "^3.0.0",
|
||||
"uuid": "^8.3.0"
|
||||
"uuid": "^8.3.0",
|
||||
"ws": "^8.12.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel-eslint": "^10.1.0",
|
||||
|
||||
@ -13,7 +13,7 @@ router.post('/signup', async (req, res) => {
|
||||
if(users.length == 0) {
|
||||
let user = new User(email, password);
|
||||
await collection.insertOne(user.toDB());
|
||||
user.token = jwt.sign({ email }, '#IWantToBelieve', { expiresIn: '365d' });
|
||||
user.token = jwt.sign({ email }, process.env.JWT_SECRET_AUTH, { expiresIn: process.env.JWT_EXPIRATION_TIME });
|
||||
res.send({ success: true, data: user });
|
||||
} else {
|
||||
res.send(makeError('User already exists'));
|
||||
@ -40,7 +40,7 @@ router.post('/login', async (req, res) => {
|
||||
return;
|
||||
}
|
||||
|
||||
me.token = jwt.sign({ email }, '#IWantToBelieve', { expiresIn: '365d' });
|
||||
me.token = jwt.sign({ email }, process.env.JWT_SECRET_AUTH, { expiresIn: process.env.JWT_EXPIRATION_TIME });
|
||||
res.send({ success: true, data: me });
|
||||
} else {
|
||||
res.send(makeError('Incorrect login or password', errorCodes.invalidLoginOrPassword));
|
||||
@ -67,12 +67,12 @@ router.post('/signIn', async (req, res) => {
|
||||
return;
|
||||
}
|
||||
|
||||
me.token = jwt.sign({ email }, '#IWantToBelieve', { expiresIn: '365d' });
|
||||
me.token = jwt.sign({ email }, process.env.JWT_SECRET_AUTH, { expiresIn: process.env.JWT_EXPIRATION_TIME });
|
||||
res.send({ success: true, data: me });
|
||||
} else {
|
||||
let user = new User(email, password);
|
||||
await users.insertOne(user.toDB());
|
||||
user.token = jwt.sign({ email }, '#IWantToBelieve', { expiresIn: '365d' });
|
||||
user.token = jwt.sign({ email }, process.env.JWT_SECRET_AUTH, { expiresIn: process.env.JWT_EXPIRATION_TIME });
|
||||
res.send({ success: true, data: user });
|
||||
}
|
||||
} catch(ex) {
|
||||
|
||||
@ -75,7 +75,7 @@ router.post('/check', async (req, res) => {
|
||||
} else if(autocod.status == 'rejected') {
|
||||
vehicle = vin01.value;
|
||||
Object.assign(vehicle.debugInfo, autocod.reason.debugInfo);
|
||||
if(!vehicle.brand.name.normalized) {
|
||||
if(!vehicle.brand?.name?.normalized) {
|
||||
throw autocod.reason;
|
||||
}
|
||||
} else {
|
||||
@ -140,7 +140,11 @@ router.post('/check', async (req, res) => {
|
||||
router.get('/', async (req, res) => {
|
||||
const { email } = req.user;
|
||||
const { pageToken, sortBy, sortOrder } = req.query;
|
||||
const pageSize = 50;
|
||||
|
||||
let pageSize = parseInt(req.query.pageSize);
|
||||
if(isNaN(pageSize)) {
|
||||
pageSize = 50;
|
||||
}
|
||||
|
||||
try {
|
||||
let finalQuery = Utils.makeVehiclesSearchQuery(req.query, email);
|
||||
|
||||
@ -1,8 +1,23 @@
|
||||
class Utils {
|
||||
static makeVehiclesSearchQuery(queryParams, email) {
|
||||
const { query, brand, model, color, regions, fromDate, toDate, addedBy, fromDateUpdated, toDateUpdated, year } = queryParams;
|
||||
const {
|
||||
query,
|
||||
brand,
|
||||
model,
|
||||
color,
|
||||
regions,
|
||||
fromDate,
|
||||
toDate,
|
||||
addedBy,
|
||||
fromDateUpdated,
|
||||
toDateUpdated,
|
||||
fromLocationDate,
|
||||
toLocationDate,
|
||||
year,
|
||||
scope
|
||||
} = queryParams;
|
||||
|
||||
let numberQuery = Utils.makeNumberQuery(query, regions?.split(',') ?? []);
|
||||
let numberQuery = Utils.makeNumberQuery(scope, query, regions?.split(',') ?? []);
|
||||
let findQuery = {
|
||||
'brand.name.normalized': brand,
|
||||
'model.name.normalized': model,
|
||||
@ -33,6 +48,22 @@ class Utils {
|
||||
}
|
||||
}
|
||||
|
||||
if(fromLocationDate || toLocationDate) {
|
||||
let comparator = {};
|
||||
if(fromLocationDate) {
|
||||
comparator.$gte = parseFloat(fromLocationDate);
|
||||
}
|
||||
if(toLocationDate) {
|
||||
comparator.$lte = parseFloat(toLocationDate);
|
||||
}
|
||||
|
||||
findQuery.events = {
|
||||
$elemMatch: {
|
||||
date: comparator
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
if(addedBy) {
|
||||
if(addedBy == 'me') {
|
||||
findQuery.addedBy = email;
|
||||
@ -45,15 +76,28 @@ class Utils {
|
||||
return { ...findQueryFiltered, ...numberQuery };
|
||||
}
|
||||
|
||||
static makeNumberQuery(number, regions) {
|
||||
static makeNumberQuery(scope, number, regions) {
|
||||
|
||||
let mainQuery = { number: { $regex: number } };
|
||||
switch(scope) {
|
||||
case 'plateNumber':
|
||||
break;
|
||||
case 'vin':
|
||||
mainQuery = { vin1: { $regex: number } };
|
||||
break;
|
||||
case 'notes':
|
||||
mainQuery = { 'notes.text': { $regex: RegExp(number, 'i') } };
|
||||
break;
|
||||
}
|
||||
|
||||
let regionsQuery = null;
|
||||
if(regions.length > 0) {
|
||||
regionsQuery = { $or: regions.map(r => { return { number: { $regex: `\\D${r}$` } }; }) };
|
||||
}
|
||||
if(number && regionsQuery) {
|
||||
return { $and: [ { number: { $regex: number } }, regionsQuery ] };
|
||||
return { $and: [ mainQuery, regionsQuery ] };
|
||||
} else if(number) {
|
||||
return { number: { $regex: number } };
|
||||
return mainQuery;
|
||||
} else if(regionsQuery) {
|
||||
return regionsQuery;
|
||||
} else {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user