diff --git a/app.js b/app.js index 3e8b57ee9..c0dcdbe79 100755 --- a/app.js +++ b/app.js @@ -657,13 +657,6 @@ async function main() { ); }; - // Always serve the generated context directly from the distPath. - router.use( - '/static/generated', - express.static(path.join(distPath, 'static', 'generated'), { - maxAge: staticMaxAgeSecs * 1000, - }), - ); await (isDevMode() ? setupWebPackDevMiddleware(router) : setupStaticMiddleware(router)); morgan.token('gdpr_ip', req => (req.ip ? utils.anonymizeIp(req.ip) : '')); diff --git a/etc/scripts/parsed_pug_file.js b/etc/scripts/parsed_pug_file.js new file mode 100644 index 000000000..4023c84f6 --- /dev/null +++ b/etc/scripts/parsed_pug_file.js @@ -0,0 +1,30 @@ +import {execSync} from 'child_process'; +import {getHashDigest} from 'loader-utils'; +import * as pug from 'pug'; + +function execGit(command) { + const gitResult = execSync(command); + if (!gitResult) { + throw new Error(`Failed to execute ${command}`); + } + return gitResult.toString(); +} + +const gitChanges = execGit('git log --date=local --after="3 months ago" "--grep=(#[0-9]*)" --oneline') + .split('\n') + .map(line => line.match(/(?\w+) (?.*)/)) + .filter(x => x) + .map(match => match.groups); + +export default function(content) { + const filename = this.resourcePath; + const lastTime = execGit(`git log -1 --format=%cd "${filename}"`).trimEnd(); + const lastCommit = execGit(`git log -1 --format=%h "${filename}"`).trimEnd(); + const compiled = pug.compile(content.toString(), {filename}); + const source = compiled({gitChanges, lastTime, lastCommit}); + const result = { + hash: getHashDigest(source, 'sha256', 'hex', 16), + text: source.toString(), + }; + return `export default ${JSON.stringify(result)};`; +} diff --git a/lib/options-handler.js b/lib/options-handler.js index 6636cfaf3..85624482d 100755 --- a/lib/options-handler.js +++ b/lib/options-handler.js @@ -30,9 +30,7 @@ import _ from 'underscore'; import {logger} from './logger'; import {getToolTypeByKey} from './tooling'; -import {asSafeVer, countOccurrences, getHash, resolvePathFromAppRoot, splitArguments} from './utils'; - -const HashVersion = 'Compiler Explorer Policies Version 1'; +import {asSafeVer, getHash, splitArguments} from './utils'; /*** * Handles the setup of the options object passed on each page request @@ -113,21 +111,10 @@ export class ClientOptionsHandler { policies: { cookies: { enabled: cookiePolicyEnabled, - hash: cookiePolicyEnabled - ? ClientOptionsHandler.getFileHash( - resolvePathFromAppRoot('static', 'generated', 'cookies.html'), - ) - : null, key: 'cookie_status', }, privacy: { enabled: privacyPolicyEnabled, - hash: privacyPolicyEnabled - ? ClientOptionsHandler.getFileHash( - resolvePathFromAppRoot('static', 'generated', 'privacy.html'), - ) - : null, - // How we store this privacy hash on the local storage key: 'privacy_status', }, }, @@ -390,13 +377,4 @@ export class ClientOptionsHandler { getHash() { return this.optionsHash; } - - static getFileHash(path) { - if (!fs.existsSync(path)) { - logger.error(`File ${path} requested for hashing not found`); - // Should we throw? What should happen here? - } - - return getHash(fs.readFileSync(path, 'utf-8'), HashVersion); - } } diff --git a/package-lock.json b/package-lock.json index 23abebe59..6643b6f89 100644 --- a/package-lock.json +++ b/package-lock.json @@ -29,7 +29,6 @@ "file-saver": "^2.0.5", "fs-extra": "^10.0.0", "golden-layout": "^1.5.9", - "handlebars": "^4.7.7", "html-loader": "^3.0.1", "http-proxy": "^1.18.1", "husky": "^7.0.4", @@ -6927,34 +6926,6 @@ "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==", "dev": true }, - "node_modules/handlebars": { - "version": "4.7.7", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", - "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==", - "dependencies": { - "minimist": "^1.2.5", - "neo-async": "^2.6.0", - "source-map": "^0.6.1", - "wordwrap": "^1.0.0" - }, - "bin": { - "handlebars": "bin/handlebars" - }, - "engines": { - "node": ">=0.4.7" - }, - "optionalDependencies": { - "uglify-js": "^3.1.4" - } - }, - "node_modules/handlebars/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/har-schema": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", @@ -14039,18 +14010,6 @@ "node": ">=4.2.0" } }, - "node_modules/uglify-js": { - "version": "3.15.4", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.15.4.tgz", - "integrity": "sha512-vMOPGDuvXecPs34V74qDKk4iJ/SN4vL3Ow/23ixafENYvtrNvtbcgUeugTcUGRGsOF/5fU8/NYSL5Hyb3l1OJA==", - "optional": true, - "bin": { - "uglifyjs": "bin/uglifyjs" - }, - "engines": { - "node": ">=0.8.0" - } - }, "node_modules/unbox-primitive": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", @@ -15075,11 +15034,6 @@ "node": ">=0.10.0" } }, - "node_modules/wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=" - }, "node_modules/workerpool": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.1.0.tgz", @@ -20525,25 +20479,6 @@ "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==", "dev": true }, - "handlebars": { - "version": "4.7.7", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", - "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==", - "requires": { - "minimist": "^1.2.5", - "neo-async": "^2.6.0", - "source-map": "^0.6.1", - "uglify-js": "^3.1.4", - "wordwrap": "^1.0.0" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" - } - } - }, "har-schema": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", @@ -25833,12 +25768,6 @@ "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.2.tgz", "integrity": "sha512-HM/hFigTBHZhLXshn9sN37H085+hQGeJHJ/X7LpBWLID/fbc2acUMfU+lGD98X81sKP+pFa9f0DZmCwB9GnbAg==" }, - "uglify-js": { - "version": "3.15.4", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.15.4.tgz", - "integrity": "sha512-vMOPGDuvXecPs34V74qDKk4iJ/SN4vL3Ow/23ixafENYvtrNvtbcgUeugTcUGRGsOF/5fU8/NYSL5Hyb3l1OJA==", - "optional": true - }, "unbox-primitive": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", @@ -26588,11 +26517,6 @@ "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==" }, - "wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=" - }, "workerpool": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.1.0.tgz", diff --git a/package.json b/package.json index 0ab8b61da..7b32e17b0 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,6 @@ "file-saver": "^2.0.5", "fs-extra": "^10.0.0", "golden-layout": "^1.5.9", - "handlebars": "^4.7.7", "html-loader": "^3.0.1", "http-proxy": "^1.18.1", "husky": "^7.0.4", diff --git a/static/generated/changelog.html b/static/generated/changelog.html deleted file mode 100644 index cf9d5f146..000000000 --- a/static/generated/changelog.html +++ /dev/null @@ -1,9 +0,0 @@ -
- {{#each gitChanges}} -
- -
- {{/each}} -
diff --git a/static/generated/changelog.pug b/static/generated/changelog.pug new file mode 100644 index 000000000..8935c21f7 --- /dev/null +++ b/static/generated/changelog.pug @@ -0,0 +1,6 @@ +div.commits-list + each change in gitChanges + div.row.commit-entry + div.col-sm-12 + a(href="https://github.com/compiler-explorer/compiler-explorer/commit/#{change.hash}" + rel="noreferrer noopener" target="_blank") #{change.description} diff --git a/static/generated/cookies.html b/static/generated/cookies.html deleted file mode 100644 index e62f522a4..000000000 --- a/static/generated/cookies.html +++ /dev/null @@ -1,78 +0,0 @@ - - - - - - - - - - Last changed on: - - (diff) - - - -

Compiler Explorer Cookie Policy

- -

- Browsers support the storing and sending back of small text files called "Cookies". These cookie files can be used - (amongst other things) to help track the usage of a website. See - the Mozilla - description of cookies for more details. -

- -

- Compiler Explorer uses Google Analytics, which in turn uses cookies. Google Analytics allows us to see how many - individual users of Compiler Explorer there are, how often users visit us, the average amount of time spent on the - site, the frequency and distribution of compilers selected, and so on. It is invaluable in helping us make - decisions in prioritising work on the site. It's important to note that these cookies are anonymous: we don't know - who each individual user is. Our Google Analytics settings prevent data being retained for more than 14 months. The - cookie stored is a first party cookie: you will find it in your browser under "godbolt.org" cookies. -

- -

- Your privacy is important to us, and you may opt out of this tracking at any time using the buttons on this dialog, - with no loss of access or functionality of Compiler Explorer. -

- -

Necessary Local Storage

-

- To store your preferred options between sessions, such as your input code and user interface layout, we make use of - your browser's local storage, where we place: -

- - - -

- Note that the usage of local storage is necessary for the proper functioning of the site, and it won't be disabled - if you choose to not grant cookie usage consent. This information is not used to track any user identifying - information. The data stored locally is only that required by the site to function. -

- -

How to control the cookies

-

- You can change your cookie consent decision on Compiler Explorer by pressing one of the following buttons: -

- - diff --git a/static/generated/cookies.pug b/static/generated/cookies.pug new file mode 100644 index 000000000..268d59820 --- /dev/null +++ b/static/generated/cookies.pug @@ -0,0 +1,63 @@ +// Be aware: modifying this file in any way will cause a pop-up to users telling them the cookie policy has changed. +html(lang="en") + body + span(id="last-changed") + | Last changed on: + | + time(id="changed-date" datetime=lastTime) #{lastTime} + | + | ( + i + a(href="https://github.com/compiler-explorer/compiler-explorer/commit/#{lastCommit}" target="_blank") diff + | ) + + h2 Compiler Explorer Cookie Policy + + p + | Browsers support the storing and sending back of small text files called "Cookies". These cookie files can be + | used (amongst other things) to help track the usage of a website. See + | + a(href="https://developer.mozilla.org/docs/Web/HTTP/Cookies" + target="_blank" + rel="noreferrer noopener") the Mozilla description of cookies + | + | for more details. + + p + | Compiler Explorer uses Google Analytics, which in turn uses cookies. Google Analytics allows us to see how many + | individual users there are, how often users visit us, the average amount of time spent on the + | site, the frequency and distribution of compilers selected, and so on. It is invaluable in helping us make + | decisions in prioritising work on the site. It's important to note that these cookies are anonymous: we don't know + | who each individual user is. Our Google Analytics settings prevent data being retained for more than 14 months. The + | cookie stored is a first party cookie: you will find it in your browser under "godbolt.org" cookies. + + p + | Your privacy is important to us, and you may opt out of this tracking at any time using the buttons on this dialog, + | with no loss of access or functionality of Compiler Explorer. + + h2 #[span(style="color: darkslategray") Necessary] Local Storage + + p + | To store your preferred options between sessions, such as your input code and user interface layout, we make use of + | your browser's local storage, where we place: + + ul + li The current page state, such as: + ul + li Your current code + li Selected compilers and their options + li Pane layout + li Font sizes + li Your settings as shown in the settings popup (which can be found at: More > Settings), such as: + ul + li Your theme selection + li The default language + li Compile-as-you-type settings + + p + | Note that the usage of local storage is necessary for the proper functioning of the site, and it won't be disabled + | if you choose to not grant cookie usage consent. This information is not used to track any user identifying + | information. The data stored locally is only that required by the site to function. + + h3 How to control the cookies + p You can change your cookie consent decision on Compiler Explorer by pressing one of the following buttons: diff --git a/static/generated/privacy.html b/static/generated/privacy.html deleted file mode 100644 index e7fdd94f8..000000000 --- a/static/generated/privacy.html +++ /dev/null @@ -1,174 +0,0 @@ - - - - - - - - - - Last changed on: - - (diff) - - - -

Compiler Explorer Privacy Policy

- -

- Thanks for your interest in what Compiler Explorer does with your data. Data protection is really - important to the Compiler Explorer team, and we want to be very clear about what we do with your data. -

- -

Who we are

- -

- Compiler Explorer was created by and is primarily administrated by - Matt Godbolt, - along with a number of volunteers (including, but not limited to those listed in our "Authors" documentation). - It is run on a best-effort basis, and is not a commercial product. We do our best - to keep your data safe, but welcome help from the community: See our - GitHub project page if you wish to help. -

- -

Your data

- -

- In order to process compilation and execution requests, your browser sends the source code you typed in the editor - window along with your chosen compiler and options to the Compiler Explorer servers. There, the source code is - written to disk and your chosen compiler is invoked on it. If your request was to have your code executed, the - resulting executable is run. The outputs from compilation and execution are processed and sent back to your web - browser, where they're shown. Shortly after this process completes, your source code is deleted from disk. If, in - processing your query, an issue with Compiler Explorer is found, your code may be kept for up to a week in order to - help debug and diagnose the problem. Only the Compiler Explorer team will have access to your code, and only for the - purposes of debugging the site: we will never share your code with anyone. -

- -

- If you choose a Microsoft compiler, then your code may be sent to and compiled on a machine administrated by - Microsoft. Such code is covered by the Microsoft - Privacy Policy. -

- -

- The source code and options are also subject to a one-way hash, which is used to cache the results to speed up - subsequent compilations of the same code. The cache is in-memory and on-disk. It's impossible to reconstruct the - source code from the hash, but the resulting assembly code or binary output (the compilation result) is stored as - plain text. There's no way to enumerate the in-memory cache contents. In exceptional cases, administrator members of - the Compiler Explorer team may be able to enumerate the disk caches and retrieve the compilation output, but with no - way to trace it back to the source code. -

- -

- In short: your source code is stored in plaintext for the minimum time feasible to be able to process your request. - After that, it is discarded and is inaccessible. In very rare cases your code may be kept for a little longer (at - most a week) to help debug issues in Compiler Explorer. -

- -

Short links

- -

- If you choose to share your code using the "Share" dropdown, then the user interface state including the source code - is stored. For a "Full" link, this information is encoded into the URL as a URL hash (e.g. - https://godbolt.org/#ui_state_and_code). For short URLs, the interface state is stored on Compiler - Explorer's servers, and a shortened name uniquely referring to this data is returned. The shortened name comes from - a secure hash of the state, and without knowing the name it is infeasible to access the data. Only Compiler Explorer - administrators can access this data directly. Obfuscated IP addresses and creation time are stored alongside this - data, to enable spam detection. Links of this form look like https://godbolt.org/z/SHORTNAME. -

- -

- Prior to storing data itself, Compiler Explorer used an external URL shortening service - (goo.gl) and the resulting short URL was rewritten as - https://godbolt.org/g/SHORTURLPART. The storage for the user experience state in this case remains with - the short URL provider, not Compiler Explorer. -

- -

Application, web and error logs

- -

- Compiler Explorer keeps application logs, which contain semi-anonymised IP addresses, but no other personally - identifying information. When a long URL is clicked, the hash part of the URL is not sent to the server, so the user - state (including the source code) is NOT exposed in the web log. If a user clicks a short URL, then the short form - IS exposed in the web log (as https://godbolt.org/g/SHORTURLPART) and from this the source code can be - retrieved. As such, if you create a short URL of your code, your source code and other user state can in principle - be retrieved from the web log of Compiler Explorer. -

- -

- Compiler Explorer uses Amazon's web serving, load balancing and edge caching systems. In order to debug and diagnose - Compiler Explorer, to help track down and block Denial of Service attacks, and to gather statistics about Compiler - Explorer's performance and usage, the logs from these systems are archived. These logs contain the full IP addresses - of requests. They are kept for no more than one month, after which they are permanently deleted. -

- -

- If your web browser experiences an error, we use a third party reporting system (Sentry). This keeps information, including your IP address and web browser user - agent, for no more than 90 days. -

- -

Executing your code

- -

- For certain configurations, we may support executing the results of your compilation on the Compiler Explorer - servers. Execution occurs in a heavily locked-down, isolated environment. We have made reasonable efforts to protect - both the Compiler Explorer site and other concurrently-processed requests from information leakage due to rogue - executions. -

- -

Cookies

- -

- Separately, Compiler Explorer uses small pieces of information stored on your computer: Cookies and Browser Local - Storage. Cookies are only used with the user's permission, and are used with external analytics services (e.g. - Google Analytics) to gather statistics on Compiler Explorer usage. This information is used to help the Compiler - Explorer team plan for future updates and hardware upgrades in order to ensure the site remains stable and - responsive. Local storage is used to remember the user's settings, source code and user interface configuration, so - that it's available when the user visits the Compiler Explorer site again. This information is not transmitted to - Compiler Explorer, except as described above in order to fulfil the user's requests. There is a - separate document covering more on this. Statistics tracking - information is kept for 14 months, after which it is removed. -

- -

Your choices

- -

- Compiler Explorer is an open source project. If you are concerned about any of the data protection measures outlined - above, or about what happens to your source code, you are encouraged to run your own local instance of Compiler - Explorer. Instructions on how to do this are on the - GitHub project page. -

- -

Compiler Explorer and the GDPR

- -

- The Compiler Explorer team believes the Compiler Explorer site is compliant with the EU's General Data Protection - Regulation (GDPR). Specifically, we store no personally identifying information, we anonymise the little data that - we do have and we do not permanently store any user data. -

- -

Name and Address of the controller

-

- The Controller for the purposes of the General Data Protection Regulation (GDPR), other data protection laws - applicable in Member states of the European Union and other provisions related to data protection is: -

- -
- Matt Godbolt
- 2626 Orrington Ave
- Evanston IL 60201 USA
- +1 312 792-7931
- matt@godbolt.org -
- - - diff --git a/static/generated/privacy.pug b/static/generated/privacy.pug new file mode 100644 index 000000000..16e2ee6d7 --- /dev/null +++ b/static/generated/privacy.pug @@ -0,0 +1,164 @@ +//Be aware: modifying this file in any way will cause a pop-up to users telling them the privacy policy has changed. +html(lang="en") + body + span(id="last-changed") + | Last changed on: + | + time(id="changed-date" datetime=lastTime) #{lastTime} + | + | ( + i + a(href="https://github.com/compiler-explorer/compiler-explorer/commit/#{lastCommit}" target="_blank") diff + | ) + + h2 Compiler Explorer Privacy Policy + + p + | Thanks for your interest in what Compiler Explorer does with your data. Data protection is really + | important to the Compiler Explorer team, and we want to be very clear about what we do with your data. + + h3 Who we are + + p + | Compiler Explorer was created by and is primarily administrated by + | + a(href="mailto:matt@godbolt.org") Matt Godbolt + | , along with a number of volunteers (including, but not limited to those listed in our " + a(href="https://github.com/compiler-explorer/compiler-explorer/blob/main/AUTHORS.md" + target="_blank" rel="noreferrer noopener") Authors + | " documentation). + | It is run on a best-effort basis, and is not a commercial product. We do our best + | to keep your data safe, but welcome help from the community: See our + | + a(href="https://github.com/compiler-explorer/compiler-explorer" + target="_blank" rel="noreferrer noopener") GitHub project page + | + | if you wish to help. + + h3 Your data + + p + | In order to process compilation and execution requests, your browser sends the source code you typed in the editor + | window along with your chosen compiler and options to the Compiler Explorer servers. There, the source code is + | written to disk and your chosen compiler is invoked on it. If your request was to have your code executed, the + | resulting executable is run. The outputs from compilation and execution are processed and sent back to your web + | browser, where they're shown. Shortly after this process completes, your source code is deleted from disk. If, in + | processing your query, an issue with Compiler Explorer is found, your code may be kept for up to a week in order to + | help debug and diagnose the problem. Only the Compiler Explorer team will have access to your code, and only for the + | purposes of debugging the site: we will never share your code with anyone. + + p + | If you choose a Microsoft compiler, then your code may be sent to and compiled on a machine administrated by + | Microsoft. Such code is covered by the + | + a(href="https://privacy.microsoft.com/en-US/privacy.pug" target="_blank") Microsoft Privacy Policy. + + p + | The source code and options are also subject to a one-way hash, which is used to cache the results to speed up + | subsequent compilations of the same code. The cache is in-memory and on-disk. It's impossible to reconstruct the + | source code from the hash, but the resulting assembly code or binary output (the compilation result) is stored as + | plain text. There's no way to enumerate the in-memory cache contents. In exceptional cases, administrator members of + | the Compiler Explorer team may be able to enumerate the disk caches and retrieve the compilation output, but with no + | way to trace it back to the source code. + + p + | In short: your source code is stored in plaintext for the minimum time feasible to be able to process your request. + | After that, it is discarded and is inaccessible. In very rare cases your code may be kept for a little longer (at + | most a week) to help debug issues in Compiler Explorer. + + h4 Short links + + p + | If you choose to share your code using the "Share" dropdown, then the user interface state including the source code + | is stored. For a "Full" link, this information is encoded into the URL as a URL hash (e.g. + | #[code https://godbolt.org/#ui_state_and_code]). For short URLs, the interface state is stored on + | Compiler Explorer's servers, and a shortened name uniquely + | referring to this data is returned. The shortened name comes from a secure hash of the state, and without + | knowing the name it is infeasible to access the data. Only Compiler Explorer administrators can access this data + | directly. Obfuscated IP addresses and creation time are stored alongside this data, to enable spam detection. + | Links of this form look like #[code https://godbolt.org/z/SHORTNAME]. + + p + | Prior to storing data itself, Compiler Explorer used an external URL shortening service ( + a(href="https://goo.gl/" target="_blank") goo.gl + | ) and the resulting short URL was rewritten as #[code https://godbolt.org/g/SHORTURLPART]. + | The storage for the user experience state in this case remains with the short URL provider, + | not Compiler Explorer. + + h4 Application, web and error logs + + p + | Compiler Explorer keeps application logs, which contain semi-anonymised IP addresses, but no other personally + | identifying information. When a long URL is clicked, the hash part of the URL is not sent to the server, so the user + | state (including the source code) is NOT exposed in the web log. If a user clicks a short URL, then the short form + | #[em is] exposed in the web log (as #[code https://godbolt.org/g/SHORTURLPART]) and from this the source code can be + | retrieved. As such, if you create a short URL of your code, your source + | code and other user state can in principle be retrieved from the web log of Compiler Explorer. + + p + | Compiler Explorer uses Amazon's web serving, load balancing and edge caching systems. In order to debug and diagnose + | Compiler Explorer, to help track down and block Denial of Service attacks, and to gather statistics about Compiler + | Explorer's performance and usage, the logs from these systems are archived. These logs contain the full IP addresses + | of requests. They are kept for no more than one month, after which they are permanently deleted. + + p + | If your web browser experiences an error, we use a third party reporting system ( + a(href="https://sentry.io/" target="_blank") Sentry + | ). This keeps information, including your IP address and web browser user agent, for no more than 90 days. + + h4 Executing your code + + p + | For certain configurations, we may support executing the results of your compilation on the Compiler Explorer + | servers. Execution occurs in a heavily locked-down, isolated environment. We have made reasonable efforts to protect + | both the Compiler Explorer site and other concurrently-processed requests from information leakage due to rogue + | executions. + + h4 Cookies + + p + | Separately, Compiler Explorer uses small pieces of information stored on your computer: Cookies and Browser Local + | Storage. Cookies are only used with the user's permission, and are used with external analytics services (e.g. + | Google Analytics) to gather statistics on Compiler Explorer usage. This information is used to help the Compiler + | Explorer team plan for future updates and hardware upgrades in order to ensure the site remains stable and + | responsive. Local storage is used to remember the user's settings, source code and user interface configuration, so + | that it's available when the user visits the Compiler Explorer site again. This information is not transmitted to + | Compiler Explorer, except as described above in order to fulfil the user's requests. There is a + | + a(href="#cookies" rel="noreferrer noopener") separate document + | + | covering more on this. Statistics tracking information is kept for 14 months, after which it is removed. + + h3 Your choices + + p + | Compiler Explorer is an open source project. If you are concerned about any of the data protection measures outlined + | above, or about what happens to your source code, you are encouraged to run your own local instance of Compiler + | Explorer. Instructions on how to do this are on the + | + a(href="https://github.com/compiler-explorer/compiler-explorer" + target="_blank" rel="noreferrer noopener") GitHub project page + | . + + h3 Compiler Explorer and the GDPR + + p + | The Compiler Explorer team believes the Compiler Explorer site is compliant with the EU's General Data Protection + | Regulation (GDPR). Specifically, we store no personally identifying information, we anonymise the little data that + | we do have and we do not permanently store any user data. + + h4 Name and Address of the controller + + p + | The Controller for the purposes of the General Data Protection Regulation (GDPR), other data protection laws + | applicable in Member states of the European Union and other provisions related to data protection is: + + div + | Matt Godbolt + br + | 2626 Orrington Ave + br + | Evanston IL 60201 USA + br + | +1 312 792-7931
+ a(href="mailto:matt@godbolt.org") matt@godbolt.org diff --git a/static/main.js b/static/main.js index 7a1fc342d..2b33c3f4f 100644 --- a/static/main.js +++ b/static/main.js @@ -69,6 +69,11 @@ var hasUIBeenReset = false; var simpleCooks = new SimpleCook(); var historyWidget = new HistoryWidget(); +var policyDocuments = { + cookies: require('./generated/cookies.pug').default, + privacy: require('./generated/privacy.pug').default, +}; + function setupSettings(hub) { var eventHub = hub.layout.eventHub; var defaultSettings = { @@ -111,7 +116,7 @@ function setupSettings(hub) { } function hasCookieConsented(options) { - return jsCookie.get(options.policies.cookies.key) === options.policies.cookies.hash; + return jsCookie.get(options.policies.cookies.key) === policyDocuments.cookies.hash; } function isMobileViewer() { @@ -130,17 +135,18 @@ function setupButtons(options) { // so we instead trigger a click here when we want it to open with this effect. Sorry! if (options.policies.privacy.enabled) { $('#privacy').on('click', function (event, data) { - $.get(window.location.origin + window.httpRoot + 'static/generated/privacy.html').done(function (policy) { - var modal = alertSystem.alert(data && data.title ? data.title : 'Privacy policy', policy); - calcLocaleChangedDate(modal); - // I can't remember why this check is here as it seems superfluous - if (options.policies.privacy.enabled) { - jsCookie.set(options.policies.privacy.key, options.policies.privacy.hash, { - expires: 365, - sameSite: 'strict', - }); - } - }); + var modal = alertSystem.alert( + data && data.title ? data.title : 'Privacy policy', + policyDocuments.privacy.text + ); + calcLocaleChangedDate(modal); + // I can't remember why this check is here as it seems superfluous + if (options.policies.privacy.enabled) { + jsCookie.set(options.policies.privacy.key, policyDocuments.privacy.hash, { + expires: 365, + sameSite: 'strict', + }); + } }); } @@ -155,19 +161,17 @@ function setupButtons(options) { ); }; $('#cookies').on('click', function () { - $.get(window.location.origin + window.httpRoot + 'static/generated/cookies.html').done(function (cookies) { - var modal = alertSystem.ask(getCookieTitle(), cookies, { - yes: function () { - simpleCooks.callDoConsent.apply(simpleCooks); - }, - yesHtml: 'Consent', - no: function () { - simpleCooks.callDontConsent.apply(simpleCooks); - }, - noHtml: 'Do NOT consent', - }); - calcLocaleChangedDate(modal); + var modal = alertSystem.ask(getCookieTitle(), policyDocuments.cookies.text, { + yes: function () { + simpleCooks.callDoConsent.apply(simpleCooks); + }, + yesHtml: 'Consent', + no: function () { + simpleCooks.callDontConsent.apply(simpleCooks); + }, + noHtml: 'Do NOT consent', }); + calcLocaleChangedDate(modal); }); } @@ -183,9 +187,7 @@ function setupButtons(options) { }); $('#changes').on('click', function () { - $.get(window.location.origin + window.httpRoot + 'static/generated/changelog.html').done(function (changelog) { - alertSystem.alert('Changelog', $(changelog)); - }); + alertSystem.alert('Changelog', $(require('./generated/changelog.pug').default.text)); }); $('#ces').on('click', function () { @@ -338,7 +340,7 @@ function initPolicies(options) { $('#privacy').trigger('click', { title: 'New Privacy Policy. Please take a moment to read it', }); - } else if (options.policies.privacy.hash !== jsCookie.get(options.policies.privacy.key)) { + } else if (policyDocuments.privacy.hash !== jsCookie.get(options.policies.privacy.key)) { // When the user has already accepted the privacy, just show a pretty notification. var ppolicyBellNotification = $('#policyBellNotification'); var pprivacyBellNotification = $('#privacyBellNotification'); @@ -355,7 +357,7 @@ function initPolicies(options) { } } simpleCooks.setOnDoConsent(function () { - jsCookie.set(options.policies.cookies.key, options.policies.cookies.hash, { + jsCookie.set(options.policies.cookies.key, policyDocuments.cookies.hash, { expires: 365, sameSite: 'strict', }); @@ -381,7 +383,7 @@ function initPolicies(options) { // '' means no consent. Hash match means consent of old. Null means new user! var storedCookieConsent = jsCookie.get(options.policies.cookies.key); if (options.policies.cookies.enabled) { - if (storedCookieConsent !== '' && options.policies.cookies.hash !== storedCookieConsent) { + if (storedCookieConsent !== '' && policyDocuments.cookies.hash !== storedCookieConsent) { simpleCooks.show(); var cpolicyBellNotification = $('#policyBellNotification'); var cprivacyBellNotification = $('#privacyBellNotification'); diff --git a/webpack.config.esm.js b/webpack.config.esm.js index 75ac5ca35..deac9d38a 100644 --- a/webpack.config.esm.js +++ b/webpack.config.esm.js @@ -22,14 +22,12 @@ // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. -import {execSync} from 'child_process'; import path from 'path'; import {fileURLToPath} from 'url'; /* eslint-disable node/no-unpublished-import */ import CopyWebpackPlugin from 'copy-webpack-plugin'; import CssMinimizerPlugin from 'css-minimizer-webpack-plugin'; -import Handlebars from 'handlebars'; import MiniCssExtractPlugin from 'mini-css-extract-plugin'; import MonacoEditorWebpackPlugin from 'monaco-editor-webpack-plugin'; import TerserPlugin from 'terser-webpack-plugin'; @@ -43,20 +41,6 @@ console.log(`webpack config for ${isDev ? 'development' : 'production'}.`); const distPath = path.resolve(__dirname, 'out', 'dist'); const staticPath = path.resolve(__dirname, 'out', 'webpack', 'static'); -function execGit(command) { - const gitResult = execSync(command); - if (!gitResult) { - throw new Error(`Failed to execute ${command}`); - } - return gitResult.toString(); -} - -const gitChanges = execGit('git log --date=local --after="3 months ago" "--grep=(#[0-9]*)" --oneline') - .split('\n') - .map(line => line.match(/(?\w+) (?.*)/)) - .filter(x => x) - .map(match => match.groups); - // Hack alert: due to a variety of issues, sometimes we need to change // the name here. Mostly it's things like webpack changes that affect // how minification is done, even though that's supposed not to matter. @@ -98,19 +82,7 @@ const plugins = [ 'window.PRODUCTION': JSON.stringify(!isDev), }), new CopyWebpackPlugin({ - patterns: [ - {from: './static/favicon.ico', to: path.resolve(distPath, 'static', 'favicon.ico')}, - { - from: './static/generated/*.html', - to: path.resolve(distPath), - toType: 'dir', - transform: (content, filename) => { - const lastTime = execGit(`git log -1 --format=%cd "${filename}"`).trimEnd(); - const lastCommit = execGit(`git log -1 --format=%h "${filename}"`).trimEnd(); - return Handlebars.compile(content.toString())({gitChanges, lastTime, lastCommit}); - }, - }, - ], + patterns: [{from: './static/favicon.ico', to: path.resolve(distPath, 'static', 'favicon.ico')}], }), ]; @@ -186,8 +158,8 @@ export default { parser: {dataUrlCondition: {maxSize: 8192}}, }, { - test: /\.(html)$/, - loader: 'html-loader', + test: /.pug$/, + loader: './etc/scripts/parsed_pug_file.js', }, { test: /\.tsx?$/,