{"id":23700774,"url":"https://github.com/redbox-mint/sails-hook-redbox-pdfgen","last_synced_at":"2025-09-03T04:31:30.967Z","repository":{"id":33660982,"uuid":"160112692","full_name":"redbox-mint/sails-hook-redbox-pdfgen","owner":"redbox-mint","description":"Hook to add PDF Generation functionality to the ReDBox Portal using Puppeteer","archived":false,"fork":false,"pushed_at":"2024-09-21T14:53:52.000Z","size":704,"stargazers_count":0,"open_issues_count":9,"forks_count":3,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-08-05T07:55:12.449Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/redbox-mint.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":"support/development/docker-compose.yml","governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-12-03T00:57:29.000Z","updated_at":"2024-08-07T04:12:59.000Z","dependencies_parsed_at":"2024-03-19T03:30:50.370Z","dependency_job_id":"7357e8e2-895b-4406-bab9-5d6eab461a48","html_url":"https://github.com/redbox-mint/sails-hook-redbox-pdfgen","commit_stats":{"total_commits":29,"total_committers":6,"mean_commits":4.833333333333333,"dds":0.6206896551724138,"last_synced_commit":"a8ae48406e064b76c728f646309203ae24dbdf41"},"previous_names":[],"tags_count":13,"template":false,"template_full_name":null,"purl":"pkg:github/redbox-mint/sails-hook-redbox-pdfgen","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/redbox-mint%2Fsails-hook-redbox-pdfgen","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/redbox-mint%2Fsails-hook-redbox-pdfgen/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/redbox-mint%2Fsails-hook-redbox-pdfgen/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/redbox-mint%2Fsails-hook-redbox-pdfgen/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/redbox-mint","download_url":"https://codeload.github.com/redbox-mint/sails-hook-redbox-pdfgen/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/redbox-mint%2Fsails-hook-redbox-pdfgen/sbom","scorecard":{"id":767467,"data":{"date":"2025-08-11","repo":{"name":"github.com/redbox-mint/sails-hook-redbox-pdfgen","commit":"08d083659f01a824a17657073fdf086f390512c6"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":1.6,"checks":[{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Code-Review","score":0,"reason":"Found 1/28 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"License","score":0,"reason":"license file not detected","details":["Warn: project does not have a license file"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":3,"reason":"branch protection is not maximal on development and all release branches","details":["Info: 'allow deletion' disabled on branch 'master'","Info: 'force pushes' disabled on branch 'master'","Info: 'branch protection settings apply to administrators' is required to merge on branch 'master'","Warn: could not determine whether codeowners review is allowed","Warn: no status checks found to merge onto branch 'master'","Warn: PRs are not required to make changes on branch 'master'; or we don't have data to detect it.If you think it might be the latter, make sure to run Scorecard with a PAT or use Repo Rules (that are always public) instead of Branch Protection settings"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: containerImage not pinned by hash: support/Dockerfile:1: pin your Docker image by updating qcifengineering/redbox-portal:develop to qcifengineering/redbox-portal:develop@sha256:38fc28079e5719ef9bbf4ea431fee53f8df8f9617e81667483edea0ce7932e5d","Warn: npmCommand not pinned by hash: support/Dockerfile:35-36","Warn: npmCommand not pinned by hash: runForDev.sh:8","Warn: npmCommand not pinned by hash: support/prepare-guest.sh:51","Info:   0 out of   1 containerImage dependencies pinned","Info:   0 out of   3 npmCommand dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 3 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Vulnerabilities","score":0,"reason":"14 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-qwcr-r2fm-qrc7","Warn: Project is vulnerable to: GHSA-v6h2-p8h4-qcjw","Warn: Project is vulnerable to: GHSA-pxg6-pf52-xh8x","Warn: Project is vulnerable to: GHSA-3xgq-45jj-v275","Warn: Project is vulnerable to: GHSA-qw6h-vgh9-j6wx","Warn: Project is vulnerable to: GHSA-fjxv-7rqg-78g4","Warn: Project is vulnerable to: GHSA-75v8-2h7p-7m2m","Warn: Project is vulnerable to: GHSA-76c9-3jph-rj3q","Warn: Project is vulnerable to: GHSA-9wv6-86v2-598j","Warn: Project is vulnerable to: GHSA-rhx6-c78j-4q9w","Warn: Project is vulnerable to: GHSA-m6fv-jmcg-4jfg","Warn: Project is vulnerable to: GHSA-cm22-4g7w-348p","Warn: Project is vulnerable to: GHSA-pq67-2wwv-3xjx","Warn: Project is vulnerable to: GHSA-8cj5-5rvv-wf4v"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-23T01:14:40.240Z","repository_id":33660982,"created_at":"2025-08-23T01:14:40.240Z","updated_at":"2025-08-23T01:14:40.240Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":273391909,"owners_count":25097254,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-03T02:00:09.631Z","response_time":76,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-12-30T09:17:25.225Z","updated_at":"2025-09-03T04:31:30.647Z","avatar_url":"https://github.com/redbox-mint.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ReDBox Portal Record PDF Generation\n\nAn installable hook for the ReDBox Portal to \nadd PDF generation functionality for records using Puppeteer.\n\n## Installation\n\nThere are a few steps to install the pieces needed for generating PDF files.\n\n### Install package\n\nIn your redbox portal root folder run the command:\n\n```npm i @researchdatabox/sails-hook-redbox-pdfgen```\n\n### Install browser that puppeteer will control\n\nModify your Dockerfile to install the puppeteer dependencies and \ninstall the browser that puppeteer will control.\n\nThe dependency of this package `puppeteer` will download known working versions of \nChrome for Testing and chrome-headless-shell.\n\nAdd to your Dockerfile:\n\n```Dockerfile\n# As the 'root' user.\n# USER root\n\n# Install dependencies for Chrome for Testing.\nRUN apt-get update \\\n    \u0026\u0026 apt-get install -y wget gnupg ca-certificates \\\n    \u0026\u0026 wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | gpg --dearmor -o /usr/share/keyrings/googlechrome-linux-keyring.gpg \\\n    \u0026\u0026 sh -c 'echo \"deb [arch=amd64 signed-by=/usr/share/keyrings/googlechrome-linux-keyring.gpg] https://dl-ssl.google.com/linux/chrome/deb/ stable main\" \u003e\u003e /etc/apt/sources.list.d/google.list' \\\n    \u0026\u0026 apt-get update \\\n    \u0026\u0026 apt-get install -y --no-install-recommends google-chrome-stable fonts-freefont-ttf libxss1 \\\n    \u0026\u0026 rm -rf /var/lib/apt/lists/* \\\n    \u0026\u0026 mkdir -p /opt/browsers \\\n    \u0026\u0026 chown node:node /opt/browsers\n\n# As the 'node' user.\n# USER node\n\n# Copy the source files.\n# COPY --chown=node:node . \u003csource-path-in-container\u003e\n\n# Set the download path to a place that is stored in the container.\nENV PUPPETEER_CACHE_DIR=/opt/browsers\nRUN cd \u003csource-path-in-container\u003e \\\n    \u0026\u0026 npm install\n```\n\n## Configuration\n\nThe service is designed to run using the record post-save trigger functionality.\nIt has the following options:\n\n### `waitForSelector`\n\nRequired: yes\n\nA [css selector](https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#pagewaitforselectorselector-options) that puppeteer will wait for before generating the PDF. \nUsually this is when the angular app has finished initialising and the selector \"div#loading.hidden\" will be satisfactory.\nIf you have components that make AJAX calls after initialisation that you need to wait on then you may need to use a different selector.\n\n\n### `pdf-prefix`\n\nRequired: yes\n\nThe prefix of the filename that will be generated. PDFs will be stored as datastreams (attachments) \nto the record with this parameter as a prefix followed by an ISO8601 datestring. \ne.g. `\u003ctype\u003e-pdf-201901021000.pdf`\n\n\n### `token`\n\nRequired: yes\n\nAn API access token that puppeteer will use to access the record. This needs to be generated for a user on the User Management page of the system.\nThe user must also have appropriate roles set so that it has appropriate permissions to view the record.\n\n### `sourceUrlBase`\n\nRequired: no\n\nDefault: `/default/rdmp/record/view`\n\nSet the base source url.\n\n### `PDFOptions`\n\nRequired: no\n\nDefault: `{format: 'A4', printBackground: true}`\n\nChange the pdf attributes.\n\n## Example configuration\n\n\nInject the API token via the hook's `index.js`.\n\nIn `index.js`:\n\n```js\nmodule.exports = function (sails) {\n  return {\n    initialize: function (cb) {\n      if (!_.isUndefined(sails.config.auth.default.local.default.token) \u0026\u0026 !_.isEmpty(sails.config.auth.default.local.default.token)) {\n        const enabledTypes = [\"\u003ctype\u003e\"];\n        for (let enabledType of enabledTypes) {\n          sails.log.verbose(`PDFService::Adding token for recordtype ${enabledType}`)\n          sails.config.recordtype[enabledType].hooks.onCreate.post[0].options.triggerConfiguration.options.token = sails.config.auth.default.local.default.token;\n          sails.config.recordtype[enabledType].hooks.onUpdate.post[0].options.triggerConfiguration.options.token = sails.config.auth.default.local.default.token;\n        }\n      }\n    }\n  };\n};\n```\n\nSet up the pdf generation task.\n\nIn `config/agendaQueue.js`:\n\n```js\nmodule.exports.agendaQueue = {\n    jobs: [\n        {\n            name: 'PDFService-CreatePDF',\n            fnName: 'rdmpservice.queuedTriggerSubscriptionHandler',\n            options: {\n                lockLifetime: 120 * 1000, // 120 seconds max runtime\n                lockLimit: 1,\n                concurrency: 1\n            }\n        }\n    ]\n};\n```\n\nConfigure when to run the pdf generation.\n\nIn `config/\u003ctype\u003e-recordtype.js`\n\n```js\nmodule.exports.recordtype = {\n  '\u003ctype\u003e': {\n    \"packageType\": \"\u003ctype\u003e\",\n    hooks: {\n      onCreate: {\n        post: [\n          {\n            function: 'sails.services.rdmpservice.queueTriggerCall',\n            options: {\n              jobName: 'PDFService-CreatePDF',\n              triggerConfiguration: {\n                function: 'sails.services.pdfservice.createPDF',\n                options: {\n                  waitForSelector: 'div#loading.hidden',\n                  pdfPrefix: '\u003ctype\u003e-pdf',\n                  token: ''\n                }\n              }\n            }\n          },\n        ]\n      },\n      onUpdate: {\n        post: [\n          {\n            function: 'sails.services.rdmpservice.queueTriggerCall',\n            options: {\n              jobName: 'PDFService-CreatePDF',\n              triggerConfiguration: {\n                function: 'sails.services.pdfservice.createPDF',\n                options: {\n                  waitForSelector: 'div#loading.hidden',\n                  pdfPrefix: '\u003ctype\u003e-pdf',\n                  token: ''\n                }\n              }\n            }\n          }\n        ]\n      }\n    }\n  }\n}\n```\n\n## Development\n\n```bash\n# This will build the npm package for `sails-hook-redbox-pdfgen` and install it into the `rbportal`.\n# To start a redbox instance for local development:\n./runForDev.sh\n\n# After making code changes:\nnpm run dev:docker:clean\n\n\n# To run tests, then clean up the test docker compose resources:\nnpm install\nnpm run dev:host\n\nnpm run test:bruno:docker\nnpm run test:bruno:docker:clean\n\n# npm run test:mocha:docker\n# npm run test:mocha:docker:clean\n\nnpm run test:docker:clean\n\n\n# To remove the database contents and all generated and cached files:\nnpm run dev:host:clean\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fredbox-mint%2Fsails-hook-redbox-pdfgen","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fredbox-mint%2Fsails-hook-redbox-pdfgen","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fredbox-mint%2Fsails-hook-redbox-pdfgen/lists"}