Compare commits

..

No commits in common. "eb4ca5919eac005819b2faa9a4407a7f6b467cbc" and "779f0707e3114393d4e698e07fc6c42dfc22e85b" have entirely different histories.

11 changed files with 1558 additions and 4398 deletions

View File

@ -19,4 +19,3 @@ MONGO_CONNECTION_STRING = "mongodb+srv://$DB_USER_NAME:$DB_USER_PASSWORD@$DB_SER
JWT_SECRET_AUTH = "" JWT_SECRET_AUTH = ""
JWT_SECRET_SHARED_REPORT = "" JWT_SECRET_SHARED_REPORT = ""
JWT_EXPIRATION_TIME = "365d"

View File

@ -2,23 +2,12 @@ const crypto = require('crypto');
const fetch = require('node-fetch'); const fetch = require('node-fetch');
const Vehicle = require('../models/vehicle'); const Vehicle = require('../models/vehicle');
const DebugInfo = require('../models/DebugInfo'); const DebugInfo = require('../models/DebugInfo');
const { Centrifuge } = require('centrifuge'); const Centrifuge = require('centrifuge');
const SockJS = require('sockjs-client'); const SockJS = require('sockjs-client');
const WebSocket = require('ws');
const baseUrl = 'https://avtocod.ru/api/v3'; 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'); 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) { function fromBase64(data) {
return Buffer.from(data, 'base64').toString('binary'); return Buffer.from(data, 'base64').toString('binary');
} }
@ -48,47 +37,10 @@ function decryptReport(report, hash) {
return JSON.parse(decrypted.toString()); 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) { function waitForReport(centrifugoConfig, channel) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
let report = null; let report = null;
let centrifuge = new Centrifuge([{ let centrifuge = new Centrifuge(centrifugoConfig.uri, { sockjs: SockJS });
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(() => { let timeout = setTimeout(() => {
centrifuge.disconnect(); centrifuge.disconnect();
@ -99,9 +51,7 @@ function waitForReport(centrifugoConfig, channel) {
} }
}, 10000); }, 10000);
const sub = centrifuge.newSubscription(channel); centrifuge.subscribe(channel, message => {
sub.on('publication', function(message) {
if(message.data.event == 'report-ready') { if(message.data.event == 'report-ready') {
clearTimeout(timeout); clearTimeout(timeout);
centrifuge.disconnect(); centrifuge.disconnect();
@ -111,7 +61,7 @@ function waitForReport(centrifugoConfig, channel) {
} }
}); });
sub.subscribe(); centrifuge.setToken(centrifugoConfig.token);
centrifuge.connect(); centrifuge.connect();
}); });
} }
@ -123,7 +73,6 @@ class AvtocodProvider {
let resp = await getJson(url); let resp = await getJson(url);
let html = await getPage(resp.report_uri); let html = await getPage(resp.report_uri);
let result = html.match(/<meta name="app-version-hash" content="(.*?)" \/>/); let result = html.match(/<meta name="app-version-hash" content="(.*?)" \/>/);
if(result == null) { if(result == null) {
throw Error('Error getting api version hash'); throw Error('Error getting api version hash');

View File

@ -16,7 +16,6 @@ module.exports = function (options) {
jsonwebtoken.verify(token, options.secret, (error, decoded) => { jsonwebtoken.verify(token, options.secret, (error, decoded) => {
if(error) { if(error) {
res.status(401).send({ success: false, error: error.message }); res.status(401).send({ success: false, error: error.message });
console.error(error);
} else { } else {
req.user = decoded; req.user = decoded;
next(); next();
@ -24,15 +23,12 @@ module.exports = function (options) {
}); });
} else { } else {
res.status(401).send({ success: false, error: 'Unsupported authorization header' }); res.status(401).send({ success: false, error: 'Unsupported authorization header' });
console.error('Unsupported authorization header');
} }
} else { } else {
res.status(401).send({ success: false, error: 'Invalid authorization header' }); res.status(401).send({ success: false, error: 'Invalid authorization header' });
console.error('Invalid authorization header');
} }
} else { } else {
res.status(401).send({ success: false, error: 'Missing authorization header' }); res.status(401).send({ success: false, error: 'Missing authorization header' });
console.error('Missing authorization header');
} }
}; };
}; };

View File

@ -14,7 +14,7 @@ module.exports = function (uri) {
connection connection
.then(function (client) { .then(function (client) {
req['db'] = client.db('autocat'); req['db'] = client.db('autocatdev');
next(); next();
}) })
.catch(function (err) { .catch(function (err) {

View File

@ -51,22 +51,9 @@ 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 () => { (async () => {
//await addUpdatedDate(); //await addUpdatedDate();
//await addDebugInfoStatus(); //await addDebugInfoStatus();
await fixNullNotes(); await fixNullEvents();
console.log('====== Done ======'); console.log('====== Done ======');
})(); })();

View File

@ -35,8 +35,8 @@ class Vehicle {
let v = new Vehicle(); let v = new Vehicle();
v.brand = { name: tech.brand.name, logo: tech.brand?.logotype?.uri }; v.brand = { name: tech.brand.name, logo: tech.brand?.logotype?.uri };
v.category = report.fields.additional_info?.vehicle.category.code; 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.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.model = tech.model ? { name: tech.model.name } : null;
v.year = tech.year; v.year = tech.year;
v.number = report.identifiers_query.query; v.number = report.identifiers_query.query;

5792
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -13,7 +13,7 @@
"dependencies": { "dependencies": {
"abort-controller": "^3.0.0", "abort-controller": "^3.0.0",
"body-parser": "^1.19.0", "body-parser": "^1.19.0",
"centrifuge": "^3.1.0", "centrifuge": "^2.8.3",
"compress": "^0.99.0", "compress": "^0.99.0",
"compression": "^1.7.4", "compression": "^1.7.4",
"cors": "^2.8.5", "cors": "^2.8.5",
@ -22,14 +22,13 @@
"express": "^4.17.1", "express": "^4.17.1",
"express-bearer-token": "^2.4.0", "express-bearer-token": "^2.4.0",
"jsonwebtoken": "^8.5.1", "jsonwebtoken": "^8.5.1",
"mongodb": "^4.13.0", "mongodb": "^3.6.1",
"node-fetch": "^2.6.1", "node-fetch": "^2.6.1",
"node-html-parser": "^2.0.0", "node-html-parser": "^2.0.0",
"response-time": "^2.3.2", "response-time": "^2.3.2",
"sockjs-client": "^1.5.2", "sockjs-client": "^1.5.2",
"utf8": "^3.0.0", "utf8": "^3.0.0",
"uuid": "^8.3.0", "uuid": "^8.3.0"
"ws": "^8.12.0"
}, },
"devDependencies": { "devDependencies": {
"babel-eslint": "^10.1.0", "babel-eslint": "^10.1.0",

View File

@ -13,7 +13,7 @@ router.post('/signup', async (req, res) => {
if(users.length == 0) { if(users.length == 0) {
let user = new User(email, password); let user = new User(email, password);
await collection.insertOne(user.toDB()); await collection.insertOne(user.toDB());
user.token = jwt.sign({ email }, process.env.JWT_SECRET_AUTH, { expiresIn: process.env.JWT_EXPIRATION_TIME }); user.token = jwt.sign({ email }, '#IWantToBelieve', { expiresIn: '365d' });
res.send({ success: true, data: user }); res.send({ success: true, data: user });
} else { } else {
res.send(makeError('User already exists')); res.send(makeError('User already exists'));
@ -40,7 +40,7 @@ router.post('/login', async (req, res) => {
return; return;
} }
me.token = jwt.sign({ email }, process.env.JWT_SECRET_AUTH, { expiresIn: process.env.JWT_EXPIRATION_TIME }); me.token = jwt.sign({ email }, '#IWantToBelieve', { expiresIn: '365d' });
res.send({ success: true, data: me }); res.send({ success: true, data: me });
} else { } else {
res.send(makeError('Incorrect login or password', errorCodes.invalidLoginOrPassword)); res.send(makeError('Incorrect login or password', errorCodes.invalidLoginOrPassword));
@ -67,12 +67,12 @@ router.post('/signIn', async (req, res) => {
return; return;
} }
me.token = jwt.sign({ email }, process.env.JWT_SECRET_AUTH, { expiresIn: process.env.JWT_EXPIRATION_TIME }); me.token = jwt.sign({ email }, '#IWantToBelieve', { expiresIn: '365d' });
res.send({ success: true, data: me }); res.send({ success: true, data: me });
} else { } else {
let user = new User(email, password); let user = new User(email, password);
await users.insertOne(user.toDB()); await users.insertOne(user.toDB());
user.token = jwt.sign({ email }, process.env.JWT_SECRET_AUTH, { expiresIn: process.env.JWT_EXPIRATION_TIME }); user.token = jwt.sign({ email }, '#IWantToBelieve', { expiresIn: '365d' });
res.send({ success: true, data: user }); res.send({ success: true, data: user });
} }
} catch(ex) { } catch(ex) {

View File

@ -75,7 +75,7 @@ router.post('/check', async (req, res) => {
} else if(autocod.status == 'rejected') { } else if(autocod.status == 'rejected') {
vehicle = vin01.value; vehicle = vin01.value;
Object.assign(vehicle.debugInfo, autocod.reason.debugInfo); Object.assign(vehicle.debugInfo, autocod.reason.debugInfo);
if(!vehicle.brand?.name?.normalized) { if(!vehicle.brand.name.normalized) {
throw autocod.reason; throw autocod.reason;
} }
} else { } else {
@ -140,11 +140,7 @@ router.post('/check', async (req, res) => {
router.get('/', async (req, res) => { router.get('/', async (req, res) => {
const { email } = req.user; const { email } = req.user;
const { pageToken, sortBy, sortOrder } = req.query; const { pageToken, sortBy, sortOrder } = req.query;
const pageSize = 50;
let pageSize = parseInt(req.query.pageSize);
if(isNaN(pageSize)) {
pageSize = 50;
}
try { try {
let finalQuery = Utils.makeVehiclesSearchQuery(req.query, email); let finalQuery = Utils.makeVehiclesSearchQuery(req.query, email);

View File

@ -1,23 +1,8 @@
class Utils { class Utils {
static makeVehiclesSearchQuery(queryParams, email) { static makeVehiclesSearchQuery(queryParams, email) {
const { const { query, brand, model, color, regions, fromDate, toDate, addedBy, fromDateUpdated, toDateUpdated, year } = queryParams;
query,
brand,
model,
color,
regions,
fromDate,
toDate,
addedBy,
fromDateUpdated,
toDateUpdated,
fromLocationDate,
toLocationDate,
year,
scope
} = queryParams;
let numberQuery = Utils.makeNumberQuery(scope, query, regions?.split(',') ?? []); let numberQuery = Utils.makeNumberQuery(query, regions?.split(',') ?? []);
let findQuery = { let findQuery = {
'brand.name.normalized': brand, 'brand.name.normalized': brand,
'model.name.normalized': model, 'model.name.normalized': model,
@ -48,22 +33,6 @@ 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) {
if(addedBy == 'me') { if(addedBy == 'me') {
findQuery.addedBy = email; findQuery.addedBy = email;
@ -76,28 +45,15 @@ class Utils {
return { ...findQueryFiltered, ...numberQuery }; return { ...findQueryFiltered, ...numberQuery };
} }
static makeNumberQuery(scope, number, regions) { static makeNumberQuery(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; let regionsQuery = null;
if(regions.length > 0) { if(regions.length > 0) {
regionsQuery = { $or: regions.map(r => { return { number: { $regex: `\\D${r}$` } }; }) }; regionsQuery = { $or: regions.map(r => { return { number: { $regex: `\\D${r}$` } }; }) };
} }
if(number && regionsQuery) { if(number && regionsQuery) {
return { $and: [ mainQuery, regionsQuery ] }; return { $and: [ { number: { $regex: number } }, regionsQuery ] };
} else if(number) { } else if(number) {
return mainQuery; return { number: { $regex: number } };
} else if(regionsQuery) { } else if(regionsQuery) {
return regionsQuery; return regionsQuery;
} else { } else {