Compare commits

..

1 commit

Author SHA1 Message Date
71fce6db36 Aggiorna api_v1/scanphoto.js 2026-02-20 18:49:12 +08:00
6 changed files with 328 additions and 444 deletions

7
.env
View file

@ -1,7 +0,0 @@
SERVER_PROTOCOL=https
SERVER_HOST=192.168.1.4
SERVER_PORT=4000
BASE_URL=https://prova.patachina.it
EMAIL=fabio@gmail.com
PASSWORD=master66

View file

@ -1,122 +1,223 @@
// api_v1/scanphoto.js
require('dotenv').config(); require('dotenv').config();
const fs = require('fs'); const fs = require('fs');
const fsp = require('fs/promises');
const path = require('path'); const path = require('path');
const crypto = require('crypto');
const ExifReader = require('exifreader'); const ExifReader = require('exifreader');
const sharp = require('sharp'); const sharp = require('sharp');
const axios = require('axios'); const axios = require('axios');
const BASE_URL = process.env.BASE_URL; const BASE_URL = process.env.BASE_URL; // es: https://prova.patachina.it/api
const EMAIL = process.env.EMAIL; const EMAIL = process.env.EMAIL;
const PASSWORD = process.env.PASSWORD; const PASSWORD = process.env.PASSWORD;
const WEB_ROOT = 'public'; // cartella radice dei file serviti dal web server
// Estensioni supportate (puoi ampliarle)
const SUPPORTED_EXTS = new Set(['.jpg', '.jpeg', '.png', '.webp', '.heic', '.heif']);
// ----------------------------------------------------- // -----------------------------------------------------
// LOGIN → ottiene token JWT // UTILS
// ----------------------------------------------------- // -----------------------------------------------------
async function getToken() { function toPosix(p) {
// normalizza gli slash per il web (URL-friendly)
return p.split(path.sep).join('/');
}
function sha256(s) {
return crypto.createHash('sha256').update(s).digest('hex');
}
function inferMimeFromExt(ext) {
switch (ext.toLowerCase()) {
case '.jpg':
case '.jpeg': return 'image/jpeg';
case '.png': return 'image/png';
case '.webp': return 'image/webp';
case '.heic':
case '.heif': return 'image/heic';
default: return 'application/octet-stream';
}
}
// EXIF "YYYY:MM:DD HH:mm:ss" -> ISO-8601 UTC
function parseExifDateUtc(s) {
if (!s) return null;
const re = /^(\d{4}):(\d{2}):(\d{2}) (\d{2}):(\d{2}):(\d{2})$/;
const m = re.exec(s);
if (!m) return null;
const dt = new Date(Date.UTC(+m[1], +m[2]-1, +m[3], +m[4], +m[5], +m[6]));
return dt.toISOString(); // es. "2017-08-19T11:30:14.000Z"
}
function mapGps(gps) {
if (!gps) return null;
const lat = gps.Latitude;
const lng = gps.Longitude;
const alt = gps.Altitude;
if (lat == null || lng == null) return null;
return {
lat: typeof lat === 'number' ? lat : Number(lat),
lng: typeof lng === 'number' ? lng : Number(lng),
alt: (alt == null) ? null : (typeof alt === 'number' ? alt : Number(alt))
};
}
// -----------------------------------------------------
// LOGIN: ottieni e riusa il token
// -----------------------------------------------------
let cachedToken = null;
async function getToken(force = false) {
if (cachedToken && !force) return cachedToken;
try { try {
const res = await axios.post(`${BASE_URL}/auth/login`, { const res = await axios.post(`${BASE_URL}/auth/login`, { email: EMAIL, password: PASSWORD });
email: EMAIL, cachedToken = res.data.token;
password: PASSWORD return cachedToken;
});
return res.data.token;
} catch (err) { } catch (err) {
console.error("ERRORE LOGIN:", err.message); console.error("ERRORE LOGIN:", err.message);
return null; return null;
} }
} }
async function postWithAuth(url, payload) {
let token = await getToken();
if (!token) throw new Error('Token assente');
try {
return await axios.post(url, payload, {
headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json" }
});
} catch (err) {
// Se scaduto, prova una volta a rinnovare
if (err.response && err.response.status === 401) {
token = await getToken(true);
if (!token) throw err;
return await axios.post(url, payload, {
headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json" }
});
}
throw err;
}
}
// ----------------------------------------------------- // -----------------------------------------------------
// INVIA FOTO AL SERVER // INVIA FOTO AL SERVER
// ----------------------------------------------------- // -----------------------------------------------------
async function sendPhoto(json) { async function sendPhoto(json) {
const token = await getToken();
if (!token) {
console.error("Token non ottenuto, impossibile inviare foto");
return;
}
try { try {
await axios.post(`${BASE_URL}/photos`, json, { await postWithAuth(`${BASE_URL}/photos`, json);
headers: {
Authorization: `Bearer ${token}`,
"Content-Type": "application/json"
}
});
} catch (err) { } catch (err) {
console.error("Errore invio foto:", err.message); console.error("Errore invio foto:", err.message);
} }
} }
// ----------------------------------------------------- // -----------------------------------------------------
// CREA THUMBNAILS // CREA THUMBNAILS (min: 100px lato lungo, avg: 400px lato lungo)
// ----------------------------------------------------- // -----------------------------------------------------
async function createThumbnails(filePath, thumbMinPath, thumbAvgPath) { async function createThumbnails(filePath, thumbMinPath, thumbAvgPath) {
try { try {
await sharp(filePath) await sharp(filePath)
.resize(100, 100, { fit: "inside" }) .resize({ width: 100, height: 100, fit: "inside", withoutEnlargement: true })
.withMetadata() .withMetadata()
.toFile(thumbMinPath); .toFile(thumbMinPath);
await sharp(filePath) await sharp(filePath)
.resize(400) .resize({ width: 400, withoutEnlargement: true })
.withMetadata() .withMetadata()
.toFile(thumbAvgPath); .toFile(thumbAvgPath);
} catch (err) { } catch (err) {
console.error("Errore creazione thumbnails:", err.message); console.error("Errore creazione thumbnails:", err.message, filePath);
} }
} }
// ----------------------------------------------------- // -----------------------------------------------------
// SCANSIONE RICORSIVA // SCANSIONE RICORSIVA (asincrona, con metadati extra)
// ----------------------------------------------------- // -----------------------------------------------------
async function scanDir(dir, ext, results = []) { async function scanDir(dir, results = []) {
const files = fs.readdirSync(dir); const files = await fsp.readdir(dir, { withFileTypes: true });
for (const file of files) { for (const dirent of files) {
const filePath = path.join(dir, file); const filePath = path.join(dir, dirent.name);
const stat = fs.statSync(filePath);
if (stat.isDirectory()) { if (dirent.isDirectory()) {
await scanDir(filePath, ext, results); await scanDir(filePath, results);
continue; continue;
} }
if (path.extname(file).toLowerCase() !== ext) continue; const ext = path.extname(dirent.name).toLowerCase();
if (!SUPPORTED_EXTS.has(ext)) continue;
console.log("Trovato:", file); console.log("Trovato:", dirent.name);
const relDir = dir.replace("public/", ""); // Directory relativa rispetto a WEB_ROOT (es. "photos/original/...")
const thumbDir = path.join("public", relDir.replace("original", "thumbs")); const relDir = toPosix(path.relative(WEB_ROOT, dir));
const relFile = toPosix(path.join(relDir, dirent.name)); // path relativo (web-safe)
if (!fs.existsSync(thumbDir)) { // Cartella thumbs parallela a original
fs.mkdirSync(thumbDir, { recursive: true }); const thumbDirAbs = path.join(WEB_ROOT, relDir.replace(/original/i, 'thumbs'));
} await fsp.mkdir(thumbDirAbs, { recursive: true });
const baseName = path.parse(file).name; const baseName = path.parse(dirent.name).name;
const extName = path.parse(file).ext; const extName = path.parse(dirent.name).ext;
const thumbMin = path.join(thumbDir, `${baseName}_min${extName}`); // Path ASSOLUTI dei file thumb sul filesystem
const thumbAvg = path.join(thumbDir, `${baseName}_avg${extName}`); const thumbMinAbs = path.join(thumbDirAbs, `${baseName}_min${extName}`);
const thumbAvgAbs = path.join(thumbDirAbs, `${baseName}_avg${extName}`);
await createThumbnails(filePath, thumbMin, thumbAvg); await createThumbnails(filePath, thumbMinAbs, thumbAvgAbs);
// EXIF // Path RELATIVI (web) per il JSON
const thumbMinRel = toPosix(path.relative(WEB_ROOT, thumbMinAbs)); // es. "photos/thumbs/..._min.jpg"
const thumbAvgRel = toPosix(path.relative(WEB_ROOT, thumbAvgAbs));
// EXIF (expanded: true per avere gps strutturato come nel tuo attuale)
let tags = {}; let tags = {};
try { try {
tags = await ExifReader.load(filePath, { expanded: true }); tags = await ExifReader.load(filePath, { expanded: true });
} catch {} } catch (err) {
// nessun EXIF, ok
}
const timeRaw = tags?.exif?.DateTimeOriginal?.value?.[0] || null;
const isoUtc = parseExifDateUtc(timeRaw);
const gps = mapGps(tags?.gps);
const time = tags?.exif?.DateTimeOriginal?.value?.[0] || null; // Metadati immagine (width/height/size_bytes, mime)
const gps = tags?.gps || null; let width = null, height = null, size_bytes = null;
try {
const meta = await sharp(filePath).metadata();
width = meta.width || null;
height = meta.height || null;
const st = await fsp.stat(filePath);
size_bytes = st.size;
} catch (err) {
console.warn("Impossibile leggere metadata immagine:", err.message);
try {
const st = await fsp.stat(filePath);
size_bytes = st.size;
} catch {}
}
const mime_type = inferMimeFromExt(ext);
// ID stabile (se non vuoi usare quello del DB lato server)
const stableId = sha256(relFile);
results.push({ results.push({
name: file, // campi "nuovi"/normalizzati
path: relDir + "/" + file, id: stableId, // oppure lascia che lo generi il DB e rimuovi questo campo
thub1: thumbMin.replace("public/", ""), name: dirent.name,
thub2: thumbAvg.replace("public/", ""), path: relFile, // <== RELATIVO, web-safe (non contiene dominio)
gps, thub1: thumbMinRel, // <== RELATIVO
data: time, thub2: thumbAvgRel, // <== RELATIVO
gps, // {lat,lng,alt} oppure null
data: timeRaw, // EXIF originale (se vuoi mantenerlo)
taken_at: isoUtc, // ISO-8601 UTC (comodo per indicizzazione lato app)
mime_type,
width,
height,
size_bytes,
location: null location: null
}); });
} }
@ -130,10 +231,11 @@ async function scanDir(dir, ext, results = []) {
async function scanPhoto(dir) { async function scanPhoto(dir) {
console.log("Inizio scansione:", dir); console.log("Inizio scansione:", dir);
const photos = await scanDir(dir, ".jpg"); const photos = await scanDir(dir);
console.log("Trovate", photos.length, "foto"); console.log("Trovate", photos.length, "foto");
// invio seriale; se vuoi parallelizzare, limita la concorrenza (es. p-limit)
for (const p of photos) { for (const p of photos) {
await sendPhoto(p); await sendPhoto(p);
} }
@ -142,3 +244,6 @@ async function scanPhoto(dir) {
} }
module.exports = scanPhoto; module.exports = scanPhoto;
module.exports = scanPhoto;

View file

@ -1,182 +0,0 @@
const fs = require('fs');
const path = require('path');
const ExifReader = require('exifreader');
const sharp = require('sharp');
const axios = require('axios');
const loc = require('./geo.js');
//var productsDatabase = { photos: []}
//var i = 1;
//var s = 0;
//console.log("start search");
async function searchFile(dir, fileExt) {
var i = 1;
var s = 0;
s++;
// read the contents of the directory
console.log("è una directory?");
if(fs.existsSync('./public/photos')){
var ff = fs.statSync('./public/photos');
if(!ff.isDirectory()){
console.log("non è una dir");
};
};
const files = fs.readdirSync(dir);
// search through the files
for (let k = 0; k < files.length; k++) {
file = files[k];
const filePath = path.join(dir, file);
// get the file stats
const fileStat = fs.statSync(filePath);
// if the file is a directory, recursively search the directory
if (fileStat.isDirectory()) {
await searchFile(filePath, fileExt);
} else if (path.extname(file).toLowerCase() == fileExt) {
// if the file is a match, print it
var dd = dir.split("/");
var d = dd.slice(1);
var d1 = dd.slice(1);
d1[1]= "thumbs";
var ff = file.split(".");
var fn = ff.slice(0,-1).join(".");
var f1 = fn+'_min'+'.'+ff.at(-1);
var f2 = fn+'_avg'+'.'+ff.at(-1);
var f3 = fn+'_sharp'+'.'+ff.at(-1);
var extFilePath = path.join(d.join("/"),file);
var extThumbMinPath = path.join(d1.join("/"),f1);
var extThumbAvgPath = path.join(d1.join("/"),f2);
var extThumbSharpPath = path.join("public",d1.join("/"),f3);
var thumbMinPath = path.join("public",extThumbMinPath);
var thumbAvgPath = path.join("public",extThumbAvgPath);
var dt = path.join("public",d1.join("/"));
if (!fs.existsSync(dt)){
fs.mkdirSync(dt, { recursive: true });
}
var data;
try {
data = fs.readFileSync(filePath);
} catch (err) {
//console.error(err);
}
const tags = await ExifReader.load(filePath, {expanded: true});
//console.log(tags);
var time = tags.exif.DateTimeOriginal;
if (time === undefined){} else {time=time.value[0]}
var gps = tags['gps'];
//console.log(gps.Latitude);
//console.log(gps.latitude);
//var loc;
var locat;
//console.log("ora");
if (gps === undefined){} else {
// locat = await loc(gps.Longitude,gps.Latitude);
}
//if (time === undefined ){console.log(filePath)}
//console.log("read: "+filePath);
await sharp(data)
.resize(100,100,"inside")
.withMetadata()
.toFile(thumbMinPath, (err, info) => {});
await sharp(data)
.resize(400)
.withMetadata()
.toFile(thumbAvgPath, (err, info) => {});
console.log(i+" - "+file);
scrivi({
id: i,
name: file,
path: extFilePath,
thub1: extThumbMinPath,
thub2: extThumbAvgPath,
gps: tags['gps'],
data: time,
location: locat
});
i++;
}
if(k == files.length-1) {
if (s == 1) {
//scrivi(productsDatabase.photos);
//return;
//console.log("finito1");
//console.log(productsDatabase);
} else {
s--;
}
}
}
}
async function thumb(filePath, opt){
try {
const thumbnail = await imageThumbnail(filePath, opt);
//console.log(thumbnail);
return thumbnail;
} catch (err) {
//console.error(err);
}
}
// start the search in the current directory
async function scanPhoto(dir){
await searchFile(dir, '.jpg');
//console.log("finito2");
}
function scrivi(json) {
fetch('http://192.168.1.3:7771/auth/login', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({'email':'fabio@gmail.com', 'password':'master66'}),
})
.then(response => response.json())
.then(user1 => {
const myHeaders = new Headers();
myHeaders.append('Authorization', 'Bearer ' + user1.token);
myHeaders.append('Content-Type', 'application/json');
//console.log(myHeaders.get("Content-Type"));
//console.log(myHeaders.get("Authorization"));
fetch('http://192.168.1.3:7771/photos', {
method: 'POST',
headers: myHeaders,
body: JSON.stringify(json),
})
.then(response => response.json())
//.then(user => console.log("caricato"));
});
}
function azzera() {
fetch('http://192.168.1.3:7771/auth/login', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({'email':'fabio@gmail.com', 'password':'master66'}),
})
.then(response => response.json())
.then(user1 => {
const myHeaders = new Headers();
myHeaders.append('Authorization', 'Bearer ' + user1.token);
myHeaders.append('Content-Type', 'application/json');
//console.log(myHeaders.get("Content-Type"));
//console.log(myHeaders.get("Authorization"));
fetch('http://192.168.1.3:7771/photos', {
method: 'POST',
headers: myHeaders,
body: "",
})
.then(response => response.json())
.then(user => console.log("azzerato totalmente"));
});
}
module.exports = scanPhoto;

View file

@ -1,153 +1,190 @@
require('dotenv').config(); /**
* Require necessary libraries
const fs = require('fs'); */
const bodyParser = require('body-parser'); const fs = require('fs')
const jsonServer = require('json-server'); const bodyParser = require('body-parser')
const jwt = require('jsonwebtoken'); const jsonServer = require('json-server')
const bcrypt = require('bcrypt'); const jwt = require('jsonwebtoken')
const bcrypt = require('bcrypt')
const path = require('path'); const path = require('path');
const scanPhoto = require('./scanphoto.js'); const scanPhoto = require('./scanphoto.js')
const SECRET_KEY = process.env.JWT_SECRET || '123456789';
const EXPIRES_IN = process.env.JWT_EXPIRES || '1h';
const PORT = process.env.SERVER_PORT || 4000;
const server = jsonServer.create(); // JWT confing data
const SECRET_KEY = '123456789'
const expiresIn = '1h'
// ----------------------------------------------------- // Create server
// STATIC FILES var server = jsonServer.create()
// -----------------------------------------------------
server.use(jsonServer.defaults({
static: path.join(__dirname, '../public')
}));
// ----------------------------------------------------- // Create router
// CONFIG ENDPOINT (PUBBLICO) if(fs.existsSync('./api_v1/db.json')){
// ----------------------------------------------------- var router = jsonServer.router('./api_v1/db.json')
server.get('/config', (req, res) => {
res.json({
baseUrl: process.env.BASE_URL
});
});
// -----------------------------------------------------
// ROUTER DB
// -----------------------------------------------------
let router;
if (fs.existsSync('./api_v1/db.json')) {
router = jsonServer.router('./api_v1/db.json');
} else { } else {
const initialData = fs.readFileSync('api_v1/initialDB.json', 'utf8'); const initialData = fs.readFileSync('api_v1/initialDB.json', 'utf8');
// to update (sync) current database (db.json) file
fs.writeFileSync('api_v1/db.json', initialData); fs.writeFileSync('api_v1/db.json', initialData);
router = jsonServer.router('./api_v1/db.json'); var router = jsonServer.router('./api_v1/db.json')
} }
// ----------------------------------------------------- // Create router
// USERS DB var router = jsonServer.router('./api_v1/db.json')
// -----------------------------------------------------
const userdb = JSON.parse(fs.readFileSync('./api_v1/users.json', 'UTF-8'));
server.use(bodyParser.urlencoded({ extended: true })); // Users database
server.use(bodyParser.json()); const userdb = JSON.parse(fs.readFileSync('./api_v1/users.json', 'UTF-8'))
// ----------------------------------------------------- // Default middlewares
// JWT HELPERS server.use(bodyParser.urlencoded({ extended: true }))
// ----------------------------------------------------- server.use(bodyParser.json())
// Create a token from a payload
function createToken(payload) { function createToken(payload) {
return jwt.sign(payload, SECRET_KEY, { expiresIn: EXPIRES_IN }); return jwt.sign(payload, SECRET_KEY, { expiresIn })
} }
// Verify the token
function verifyToken(token) { function verifyToken(token) {
return jwt.verify(token, SECRET_KEY, (err, decode) => decode || err); return jwt.verify(
token,
SECRET_KEY,
(err, decode) => (decode !== undefined ? decode : err)
)
} }
// Check if the user exists in database
function isAuthenticated({ email, password }) { function isAuthenticated({ email, password }) {
return userdb.users.findIndex( return (
user => user.email === email && bcrypt.compareSync(password, user.password) userdb.users.findIndex(
) !== -1; user =>
user.email === email && bcrypt.compareSync(password, user.password)
) !== -1
)
} }
// ----------------------------------------------------- function azz(){
// RESET DB
// -----------------------------------------------------
function resetDB() {
const initialData = fs.readFileSync('api_v1/initialDB.json', 'utf8'); const initialData = fs.readFileSync('api_v1/initialDB.json', 'utf8');
// to update (sync) current database (db.json) file
fs.writeFileSync('api_v1/db.json', initialData); fs.writeFileSync('api_v1/db.json', initialData);
router.db.setState(JSON.parse(initialData)); router.db.setState(JSON.parse(initialData));
console.log('DB resettato'); console.log('DB resettato');
} }
// -----------------------------------------------------
// HOME // con 192.168.1.3:7771/ apre http:192.168.1.3:7771/public.index.html
// -----------------------------------------------------
server.get('/', (req, res) => { server.get('/', (req, res) => {
res.sendFile(path.resolve("public/index.html")); //console.log(req.query)
}); res.sendFile(path.resolve("public/index.html"))
})
// ----------------------------------------------------- // scansiona le foto
// SCAN FOTO
// -----------------------------------------------------
server.get('/scan', async (req, res) => { server.get('/scan', async (req, res) => {
resetDB(); azz();
await scanPhoto('./public/photos/original'); await scanPhoto('./public/photos/original')
console.log("Ricaricato"); console.log("Ricaricato")
res.send({ status: 'Ricaricato' }); res.send({status: 'Ricaricato'})
}); })
// -----------------------------------------------------
// FILE STATICI // esempio http:192.168.1.3:7771/files?file=mio.txt
// -----------------------------------------------------
server.get('/files', (req, res) => { server.get('/files', (req, res) => {
res.sendFile(path.resolve("public/" + req.query.file)); console.log(req.query)
res.sendFile(path.resolve("public/"+req.query.file))
})
server.get('/initDB1',(req, res, next) => {
const Data = { photos: []};
// to update (sync) current database (db.json) file
fs.writeFileSync('api_v1/db.json', JSON.stringify(Data));
router.db.setState(Data);
res.send({status: 'DB resettato'});
//res.sendStatus(200);
}); });
// ----------------------------------------------------- server.get('/initDB',(req, res, next) => {
// RESET DB MANUALE const initialData = fs.readFileSync('api_v1/initialDB.json', 'utf8');
// ----------------------------------------------------- // to update (sync) current database (db.json) file
server.get('/initDB', (req, res) => { fs.writeFileSync('api_v1/db.json', initialData);
resetDB(); router.db.setState(JSON.parse(initialData));
res.send({ status: 'DB resettato' }); //router = jsonServer.router('./api_v1/db.json')
res.send({status: 'DB resettato'});
//res.sendStatus(200);
}); });
// ----------------------------------------------------- server.get('/log', (req, res) => {
// LOGIN (PUBBLICO) console.log(server)
// ----------------------------------------------------- })
server.post('/auth/login', (req, res) => { /*
const { email, password } = req.body; server.use((req, res, next) => {
console.log(req.headers);
if (!isAuthenticated({ email, password })) { console.log(req.method);
return res.status(401).json({ status: 401, message: 'Incorrect email or password' }); console.log(req.path);
} var a = req.path.split("/");
if (req.method === 'GET' && a[1] == 'pub' && a.length > 2) {
const token = createToken({ email }); //console.log(req.headers.host);
res.status(200).json({ token }); //console.log(a.slice(2).join("/"));
}); res.status(200).sendFile(path.resolve("public/"+a.slice(2).join("/")));
//res.sendStatus(200);
// ----------------------------------------------------- } else {
// JWT MIDDLEWARE (TUTTO IL RESTO È PROTETTO)
// -----------------------------------------------------
server.use(/^(?!\/auth).*$/, (req, res, next) => {
if (!req.headers.authorization || req.headers.authorization.split(' ')[0] !== 'Bearer') {
return res.status(401).json({ status: 401, message: 'Bad authorization header' });
}
try {
verifyToken(req.headers.authorization.split(' ')[1]);
next(); next();
} catch (err) {
res.status(401).json({ status: 401, message: 'Error: access_token is not valid' });
} }
}); })
*/
server.use((req, res, next) => {
console.log(req.headers);
console.log(req.method);
console.log(req.path);
var a = req.path.split("/");
if (req.method === 'GET' && a[1] == 'pub' && a.length > 2) {
//console.log(req.headers.host);
//console.log(a.slice(2).join("/"));
res.status(200).sendFile(path.resolve("public/"+req.path));
//res.sendStatus(200);
} else {
next();
}
})
// ----------------------------------------------------- /**
// ROUTER JSON-SERVER * Method: POST
// ----------------------------------------------------- * Endpoint: /auth/login
server.use(router); */
server.post('/auth/login', (req, res) => {
const { email, password } = req.body
if (isAuthenticated({ email, password }) === false) {
const status = 401
const message = 'Incorrect email or password'
res.status(status).json({ status, message })
return
}
const token = createToken({ email, password })
res.status(200).json({ token })
})
// ----------------------------------------------------- /**
// START SERVER * Middleware: Check authorization
// ----------------------------------------------------- */
server.listen(PORT, () => { server.use(/^(?!\/auth).*$/, (req, res, next) => {
console.log(`Auth API server running on port ${PORT} ...`); if (
}); req.headers.authorization === undefined ||
req.headers.authorization.split(' ')[0] !== 'Bearer'
) {
const status = 401
const message = 'Bad authorization header'
res.status(status).json({ status, message })
return
}
try {
verifyToken(req.headers.authorization.split(' ')[1])
next()
} catch (err) {
const status = 401
const message = 'Error: access_token is not valid'
res.status(status).json({ status, message })
}
})
// Server mount
server.use(router)
server.listen(3000, () => {
console.log('Auth API server runing on port 3000 ...')
})

View file

@ -4,8 +4,8 @@
"description": "Building a Fake and JWT Protected REST API with json-server", "description": "Building a Fake and JWT Protected REST API with json-server",
"main": "index.js", "main": "index.js",
"scripts": { "scripts": {
"start-no-auth": "json-server --watch ./api_v1/db.json --host 0.0.0.0 -p 4000 -s ./public", "start": "json-server --watch ./api_v1/db.json --host 0.0.0.0 -p 4000 -s ./public",
"start": "node ./api_v1/server.js --host 0.0.0.0 -p 4000 -s ./public", "start-auth": "node ./api_v1/server.js --host 0.0.0.0 -p 4000 -s ./public",
"mock-data": "node ./api_v1/generateData.js > ./api_v1/db.json", "mock-data": "node ./api_v1/generateData.js > ./api_v1/db.json",
"hash": "node ./api_v1/tools.js", "hash": "node ./api_v1/tools.js",
"search": "node ./api_v1/search.js", "search": "node ./api_v1/search.js",

View file

@ -1,82 +1,13 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="it"> <html lang="it">
<head> <head>
<meta charset="UTF-8"> </head>
<title>Gestione Foto</title> <body>
</head>
<body>
<h1>Gestione Foto</h1> <script>
window.addEventListener("load", (event) => {
<button onclick="scan()">Scansiona</button> window.location.href = "pub/index.html";
<button onclick="readDB()">Leggi DB</button>
<button onclick="resetDB()">Reset DB</button>
<button onclick="deleteAll()">Cancella tutto</button>
<pre id="out"></pre>
<script>
let BASE_URL = null;
let tok = null;
let db = [];
async function loadConfig() {
const res = await fetch('/config');
const cfg = await res.json();
BASE_URL = cfg.baseUrl;
}
async function start() {
await loadConfig();
await login();
await readDB();
}
async function login() {
const res = await fetch(`${BASE_URL}/auth/login`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ email: 'fabio@gmail.com', password: 'master66' })
}); });
const data = await res.json(); </script>
tok = data.token; </body>
}
async function readDB() {
const res = await fetch(`${BASE_URL}/photos`, {
headers: { 'Authorization': 'Bearer ' + tok }
});
db = await res.json();
document.getElementById('out').textContent = JSON.stringify(db, null, 2);
}
async function scan() {
await fetch(`${BASE_URL}/scan`, {
headers: { 'Authorization': 'Bearer ' + tok }
});
await readDB();
}
async function resetDB() {
await fetch(`${BASE_URL}/initDB`, {
headers: { 'Authorization': 'Bearer ' + tok }
});
await readDB();
}
async function deleteAll() {
for (const item of db) {
await fetch(`${BASE_URL}/photos/${item.id}`, {
method: 'DELETE',
headers: { 'Authorization': 'Bearer ' + tok }
});
}
await readDB();
}
start();
</script>
</body>
</html> </html>