diff --git a/.gitignore b/.gitignore index 1a38b05..3209c63 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ node_modules config.local.yml +tmp diff --git a/Dockerfile b/Dockerfile index e4f94c6..fa03c6b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -14,6 +14,16 @@ RUN curl -fsSL https://deb.nodesource.com/setup_14.x | sudo -E bash - \ && apt install -y nodejs \ && rm -rf /var/lib/apt/lists/* +# Cups + +RUN useradd admin && usermod -g lpadmin admin + +COPY ctzcls-cups_1.1.0-0_amd64.deb /tmp/ +RUN chmod a+x /tmp/ctzcls-cups_1.1.0-0_amd64.deb \ + && dpkg -i /tmp/ctzcls-cups_1.1.0-0_amd64.deb + +# Printnatura + WORKDIR /printnatura COPY \ @@ -22,9 +32,6 @@ COPY \ ./ RUN npm install -COPY cupsd.conf /etc/cups/ -RUN useradd admin && usermod -g lpadmin admin - COPY \ main.js \ print-server.js \ @@ -33,9 +40,5 @@ COPY \ ./ COPY sql sql -COPY ctzcls-cups_1.1.0-0_amd64.deb /tmp/ -RUN chmod a+x /tmp/ctzcls-cups_1.1.0-0_amd64.deb \ - && dpkg -i /tmp/ctzcls-cups_1.1.0-0_amd64.deb - ENTRYPOINT ["/printnatura/entrypoint.sh"] CMD ["node", "main.js"] \ No newline at end of file diff --git a/README.md b/README.md index 8473fc9..f7df4ce 100644 --- a/README.md +++ b/README.md @@ -8,12 +8,13 @@ This project is used to print pdf, it acts as a print server. ## Installaton Clone the repository ``` -$ git clone https://gitea.verdnatura.es/verdnatura/printnatura.git +> git clone https://gitea.verdnatura.es/verdnatura/printnatura.git ``` Build ``` -$ docker build -t printnatura . +> $CUPS_PASSWORD = 1234 +> docker build --build-arg CUPS_PASSWORD -t printnatura . ``` Create file named "config.local.yml" and put your private configuration: @@ -35,12 +36,13 @@ refreshRate: 1000 Exec ``` -$ docker run --name printnatura -it --rm -v $PWD/config.local.yml:/printnatura/config.local.yml:ro -p 80:631 printnatura +> docker run --name printnatura -it --rm -v $PWD/config.local.yml:/printnatura/config.local.yml:ro -v $PWD/cupsd.conf:/etc/cups/cupsd.conf:ro -p 80:631 printnatura + ``` Bash ``` -$ docker exec -i -t printnatura bash +> docker exec -i -t printnatura bash ``` Has a graphical web interface (cupsd.conf) diff --git a/print-server.js b/print-server.js index 9328264..903719f 100644 --- a/print-server.js +++ b/print-server.js @@ -7,6 +7,7 @@ const axios = require('axios'); const yml = require('require-yml'); const selectQuery = fs.readFileSync(`sql/selectQueued.sql`).toString(); +const jobDataQuery = fs.readFileSync(`sql/jobData.sql`).toString(); const jobArgsQuery = fs.readFileSync(`sql/jobArgs.sql`).toString(); const updateQuery = fs.readFileSync(`sql/updateState.sql`).toString(); const appDir = path.dirname(require.main.filename); @@ -92,7 +93,6 @@ class PrintServer { } jobId = printJob.id; - this.method = printJob.method; await conn.query(updateQuery, ['printing', null, jobId]); await conn.commit(); @@ -102,22 +102,27 @@ class PrintServer { } try { + // Job data + const [[jobData]] = await conn.query(jobDataQuery, jobId); const args = {}; - const res = await conn.query(jobArgsQuery, jobId); - for (const row of res[0]) + const [res] = await conn.query(jobArgsQuery, jobId); + for (const row of res) args[row.name] = row.value; - try { - // Path params - const usedParams = new Set(); - let methodPath = this.method.replace(/{\w+}/g, function(match) { - const key = match.substr(1, match.length - 2); - const value = args[key]; - usedParams.add(key); - return value !== undefined ? value : match; - }); + + // Path params + const usedParams = new Set(); + const methodPath = jobData.method.replace(/{\w+}/g, function(match) { + const key = match.substr(1, match.length - 2); + const value = args[key]; + usedParams.add(key); + return value !== undefined ? value : match; + }); + let pdfData; + + for (let attempts = 0; !pdfData && attempts <= 1; attempts++) { // URL params - let params = { + const params = { access_token: this.token, userFk: printJob.userFk }; @@ -128,34 +133,34 @@ class PrintServer { const urlParams = new URLSearchParams(params); // Request - const response = await axios({ - method: 'get', - url: `${conf.salix.url}/api/${methodPath}?${urlParams.toString()}`, - responseType: 'arraybuffer', - headers: { - 'Accept': 'application/pdf' - } - }); - this.pdfData = response.data - } - catch (err) { - switch(err.response.statusText) { - case 'Unauthorized': - try { - await this.getToken(); - } catch(err) { - throw new Error(`Could not get token: ${err.message}`); + try { + const response = await axios({ + method: 'get', + url: `${conf.salix.url}/api/${methodPath}?${urlParams.toString()}`, + responseType: 'arraybuffer', + headers: { + 'Accept': 'application/pdf' } - break; + }); + pdfData = response.data; + } + catch (err) { + if (err.response?.statusText === 'Unauthorized') { + await this.getToken(); + } else + throw err; } } - const printer = printJob.printer; + + // Save PDF to disk + const printer = jobData.printer; const tmpPath = path.join(appDir, 'tmp') if (!fs.existsSync(tmpPath)) fs.mkdirSync(tmpPath) const tmpFilePath = path.join(tmpPath, `${Math.random().toString(36).substring(7)}.pdf`); - await fs.writeFile(tmpFilePath, this.pdfData, 'binary'); + await fs.writeFile(tmpFilePath, pdfData, 'binary'); + // Print PDF try { await pExec(`lp -d "${printer}" "${tmpFilePath}"`); } catch(err) { @@ -166,7 +171,7 @@ class PrintServer { await conn.query(updateQuery, ['printed', null, jobId]); if (conf.debug) - console.debug(`(${colors.yellow(jobId)}) Document has been printed`, `[${args.collectionFk}, ${printJob.report}, ${printer}]`.green); + console.debug(`(${colors.yellow(jobId)}) Document has been printed`, `[${args.collectionFk}, ${jobData.report}, ${printer}]`.green); await fs.unlink(tmpFilePath); } catch (err) { diff --git a/sql/jobData.sql b/sql/jobData.sql new file mode 100644 index 0000000..0cf2af4 --- /dev/null +++ b/sql/jobData.sql @@ -0,0 +1,7 @@ +SELECT r.name report, + p.name printer, + r.method + FROM printQueue pq + JOIN report r ON r.id = pq.reportFk + JOIN printer p ON p.id = pq.printerFk + WHERE pq.id = ? \ No newline at end of file diff --git a/sql/selectQueued.sql b/sql/selectQueued.sql index cddc292..f931a47 100644 --- a/sql/selectQueued.sql +++ b/sql/selectQueued.sql @@ -1,15 +1,9 @@ SELECT pq.id, - r.name report, - p.name printer, - pqa.name arg, - pqa.value, - r.method, pq.workerFk userFk FROM printQueue pq JOIN report r ON r.id = pq.reportFk - JOIN printQueueArgs pqa ON pqa.printQueueFk = pq.id - LEFT JOIN printer p ON p.id = pq.printerFk WHERE pq.statusCode = 'queued' - AND NOT r.method IS NULL + AND r.method IS NOT NULL ORDER BY pq.priorityFk ASC - LIMIT 1 \ No newline at end of file + LIMIT 1 + FOR UPDATE