From 3a5d3ba068653536b19583676cf45acf83db23f0 Mon Sep 17 00:00:00 2001 From: Ashwin Ramaswami Date: Sat, 20 Aug 2022 19:25:39 +0000 Subject: [PATCH 01/12] Set up CSP, unpkg -> jsdelivr --- ambuda/__init__.py | 5 +++++ ambuda/templates/base.html | 2 +- ambuda/templates/header-main-footer.html | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/ambuda/__init__.py b/ambuda/__init__.py index 6f6ebcce..0536cfff 100644 --- a/ambuda/__init__.py +++ b/ambuda/__init__.py @@ -119,4 +119,9 @@ def create_app(config_env: str): } ) + @app.after_request + def add_security_headers(resp): + resp.headers["Content-Security-Policy"] = "default-src 'self'; script-src 'self' https://cdn.jsdelivr.net https://www.google.com https://www.gstatic.com https://plausible.io; frame-src https://www.google.com;" + return resp + return app diff --git a/ambuda/templates/base.html b/ambuda/templates/base.html index 637fc5b2..ade3f5d5 100644 --- a/ambuda/templates/base.html +++ b/ambuda/templates/base.html @@ -7,7 +7,7 @@ A breakthrough Sanskrit library. Read our library of traditional Sanskrit texts with word-by-word analysis, integrated dictionary support, and so much more. {%- endblock %}"> - + {% block title %}{% endblock %} {% block scripts %}{% endblock %} diff --git a/ambuda/templates/header-main-footer.html b/ambuda/templates/header-main-footer.html index 61bf7002..6d2af2a0 100644 --- a/ambuda/templates/header-main-footer.html +++ b/ambuda/templates/header-main-footer.html @@ -7,7 +7,7 @@ {# Load scripts before Alpine so that our init hooks are properly set up. #} - + {% endblock %} From 991d3bf1f635d2796a31cac6a341e3a3f1fd0124 Mon Sep 17 00:00:00 2001 From: Ashwin Ramaswami Date: Mon, 22 Aug 2022 19:17:47 +0000 Subject: [PATCH 02/12] Re-add favicon --- ambuda/__init__.py | 4 +++- ambuda/templates/base.html | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/ambuda/__init__.py b/ambuda/__init__.py index 0536cfff..8471586a 100644 --- a/ambuda/__init__.py +++ b/ambuda/__init__.py @@ -121,7 +121,9 @@ def create_app(config_env: str): @app.after_request def add_security_headers(resp): - resp.headers["Content-Security-Policy"] = "default-src 'self'; script-src 'self' https://cdn.jsdelivr.net https://www.google.com https://www.gstatic.com https://plausible.io; frame-src https://www.google.com;" + resp.headers[ + "Content-Security-Policy" + ] = "default-src 'self'; script-src 'self' https://cdn.jsdelivr.net https://www.google.com https://www.gstatic.com https://plausible.io; frame-src https://www.google.com; img-src 'self' data:;" return resp return app diff --git a/ambuda/templates/base.html b/ambuda/templates/base.html index ade3f5d5..637fc5b2 100644 --- a/ambuda/templates/base.html +++ b/ambuda/templates/base.html @@ -7,7 +7,7 @@ A breakthrough Sanskrit library. Read our library of traditional Sanskrit texts with word-by-word analysis, integrated dictionary support, and so much more. {%- endblock %}"> - + {% block title %}{% endblock %} {% block scripts %}{% endblock %} From 67d602feea8946667ab7fdee4f994c12e02c2f07 Mon Sep 17 00:00:00 2001 From: Ashwin Ramaswami Date: Thu, 25 Aug 2022 20:15:43 +0000 Subject: [PATCH 03/12] use flask-talisman, fix proofing --- ambuda/__init__.py | 33 +++++++++++++++++++++++++++------ ambuda/static/js/proofer.js | 4 +++- requirements.txt | 1 + 3 files changed, 31 insertions(+), 7 deletions(-) diff --git a/ambuda/__init__.py b/ambuda/__init__.py index 08fc2156..c9702909 100644 --- a/ambuda/__init__.py +++ b/ambuda/__init__.py @@ -11,6 +11,7 @@ import sentry_sdk from dotenv import load_dotenv from flask import Flask +from flask_talisman import Talisman from sentry_sdk.integrations.flask import FlaskIntegration from sqlalchemy import exc @@ -88,6 +89,26 @@ def create_app(config_env: str): app = Flask(__name__) + csp = { + "default-src": ["'self'"], + "script-src": [ + "'self'", + "https://cdn.jsdelivr.net", + "https://www.google.com", + "https://www.gstatic.com", + "https://plausible.io", + "'unsafe-eval'", + ], + "frame-src": ["https://www.google.com"], + "img-src": ["'self'", "data:"], + "style-src": ["'self'", "'unsafe-inline'"], + } + + Talisman( + app, + content_security_policy=csp, + ) + # Config app.config.from_object(config_spec) @@ -124,11 +145,11 @@ def create_app(config_env: str): } ) - @app.after_request - def add_security_headers(resp): - resp.headers[ - "Content-Security-Policy" - ] = "default-src 'self'; script-src 'self' https://cdn.jsdelivr.net https://www.google.com https://www.gstatic.com https://plausible.io; frame-src https://www.google.com; img-src 'self' data:;" - return resp + # @app.after_request + # def add_security_headers(resp): + # resp.headers[ + # "Content-Security-Policy" + # ] = "default-src 'self'; script-src 'self' https://cdn.jsdelivr.net https://www.google.com https://www.gstatic.com https://plausible.io; frame-src https://www.google.com; img-src 'self' data:; style-src 'self';" + # return resp return app diff --git a/ambuda/static/js/proofer.js b/ambuda/static/js/proofer.js index 22518372..57d2b677 100644 --- a/ambuda/static/js/proofer.js +++ b/ambuda/static/js/proofer.js @@ -1,4 +1,4 @@ -/* global Alpine, $, OpenSeadragon, IMAGE_URL */ +/* global Alpine, $, OpenSeadragon */ /* Transcription and proofreading interface. */ import { $ } from './core.ts'; @@ -53,6 +53,8 @@ export default () => ({ init() { this.loadSettings(); + const IMAGE_URL = JSON.parse(document.getElementById('image_url').innerText); + // Set `imageZoom` only after the viewer is fully initialized. this.imageViewer = initializeImageViewer(IMAGE_URL); this.imageViewer.addHandler('open', () => { diff --git a/requirements.txt b/requirements.txt index 8ab729b2..d3054055 100644 --- a/requirements.txt +++ b/requirements.txt @@ -33,6 +33,7 @@ Flask-Admin==1.6.0 Flask-Bcrypt==1.0.1 Flask-Login==0.6.1 Flask-Mail==0.9.1 +flask-talisman==1.0.0 Flask-WTF==1.0.1 fonttools==4.33.3 gevent==21.12.0 From 4834934d60841718951d1d7e6a9b277bedf72ebe Mon Sep 17 00:00:00 2001 From: Ashwin Ramaswami Date: Thu, 25 Aug 2022 20:18:12 +0000 Subject: [PATCH 04/12] update --- ambuda/__init__.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/ambuda/__init__.py b/ambuda/__init__.py index 7b223975..ac5aa1d7 100644 --- a/ambuda/__init__.py +++ b/ambuda/__init__.py @@ -145,11 +145,4 @@ def create_app(config_env: str): } ) - # @app.after_request - # def add_security_headers(resp): - # resp.headers[ - # "Content-Security-Policy" - # ] = "default-src 'self'; script-src 'self' https://cdn.jsdelivr.net https://www.google.com https://www.gstatic.com https://plausible.io; frame-src https://www.google.com; img-src 'self' data:; style-src 'self';" - # return resp - return app From d3eef29242775b8a138b7e3a9cc947e381d9c59d Mon Sep 17 00:00:00 2001 From: Ashwin Ramaswami Date: Thu, 25 Aug 2022 20:19:06 +0000 Subject: [PATCH 05/12] IMAGE_URL --- ambuda/templates/proofing/pages/edit.html | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/ambuda/templates/proofing/pages/edit.html b/ambuda/templates/proofing/pages/edit.html index c623fbe9..fe2ab57b 100644 --- a/ambuda/templates/proofing/pages/edit.html +++ b/ambuda/templates/proofing/pages/edit.html @@ -166,7 +166,5 @@

{% set image_url = url_for("site.page_image", project_slug=project.slug, page_slug=cur.slug) %} - + {% endblock %} From 6117cb182f36af3da73034556c1d0f3a160894b9 Mon Sep 17 00:00:00 2001 From: Ashwin Ramaswami Date: Thu, 25 Aug 2022 20:59:23 +0000 Subject: [PATCH 06/12] fix force_https --- ambuda/__init__.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/ambuda/__init__.py b/ambuda/__init__.py index ac5aa1d7..bf8825af 100644 --- a/ambuda/__init__.py +++ b/ambuda/__init__.py @@ -104,10 +104,7 @@ def create_app(config_env: str): "style-src": ["'self'", "'unsafe-inline'"], } - Talisman( - app, - content_security_policy=csp, - ) + Talisman(app, content_security_policy=csp, force_https=config_env != config.TESTING) # Config app.config.from_object(config_spec) From a9aba05a566424d59ba2ad1616ea4ea605f04fc1 Mon Sep 17 00:00:00 2001 From: Ashwin Ramaswami Date: Sat, 27 Aug 2022 20:51:47 +0000 Subject: [PATCH 07/12] Poll --- ambuda/static/js/main.js | 2 ++ ambuda/static/js/proofing-create-poll.js | 20 +++++++++++++++++++ .../proofing/create-project-post.html | 9 +-------- 3 files changed, 23 insertions(+), 8 deletions(-) create mode 100644 ambuda/static/js/proofing-create-poll.js diff --git a/ambuda/static/js/main.js b/ambuda/static/js/main.js index 47eee467..b598dca7 100644 --- a/ambuda/static/js/main.js +++ b/ambuda/static/js/main.js @@ -5,6 +5,7 @@ import Dictionary from './dictionary'; import Reader from './reader'; import Proofer from './proofer'; import HamburgerButton from './hamburger-button'; +import ProofingCreatePoll from './proofing-create-poll'; window.addEventListener('alpine:init', () => { Alpine.data('dictionary', Dictionary); @@ -14,6 +15,7 @@ window.addEventListener('alpine:init', () => { (() => { HamburgerButton.init(); + ProofingCreatePoll.init(); })(); // Export a few internal values to support some existing ad-hoc usage (e.g., diff --git a/ambuda/static/js/proofing-create-poll.js b/ambuda/static/js/proofing-create-poll.js new file mode 100644 index 00000000..fa7f5fe4 --- /dev/null +++ b/ambuda/static/js/proofing-create-poll.js @@ -0,0 +1,20 @@ +import { $, Server } from './core.ts'; + +export default (() => { + // Polls for status on project creation. Used only on + // templates/proofing/create-project-post.html. + function init() { + const $el = document.getElementById('proofing_polling_task_id'); + if (!$el) { + return; + } + const taskId = JSON.parse($el.innerText); + setInterval(() => { + Server.getText(`/proofing/status/${taskId}`, (text) => { + $('#progress').innerHTML = text; + }); + }, 5000); + } + + return { init }; +})(); diff --git a/ambuda/templates/proofing/create-project-post.html b/ambuda/templates/proofing/create-project-post.html index bd20ae9e..8c32e74d 100644 --- a/ambuda/templates/proofing/create-project-post.html +++ b/ambuda/templates/proofing/create-project-post.html @@ -22,13 +22,6 @@

Create new project

- + {% endblock %} From df8f8b387cb4bb3bfa6f090f9841306c37361f3d Mon Sep 17 00:00:00 2001 From: Ashwin Ramaswami Date: Sat, 27 Aug 2022 21:18:30 +0000 Subject: [PATCH 08/12] jsdelivr --- ambuda/templates/header-main-footer.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ambuda/templates/header-main-footer.html b/ambuda/templates/header-main-footer.html index d80ad017..d4195ae3 100644 --- a/ambuda/templates/header-main-footer.html +++ b/ambuda/templates/header-main-footer.html @@ -7,7 +7,7 @@ {# Load scripts before Alpine so that our init hooks are properly set up. #} - + {% endblock %} From 5fbeb88d70d131c43adf1f6cc8a15a05762c4357 Mon Sep 17 00:00:00 2001 From: Ashwin Ramaswami Date: Thu, 8 Sep 2022 22:39:24 -0400 Subject: [PATCH 09/12] Update main.js --- ambuda/static/js/main.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/ambuda/static/js/main.js b/ambuda/static/js/main.js index 40e6937a..23caec5e 100644 --- a/ambuda/static/js/main.js +++ b/ambuda/static/js/main.js @@ -7,7 +7,6 @@ import HTMLPoller from './html-poller'; import Reader from './reader'; import Proofer from './proofer'; import HamburgerButton from './hamburger-button'; -import ProofingCreatePoll from './proofing-create-poll'; import SortableList from './sortable-list'; window.addEventListener('alpine:init', () => { @@ -20,5 +19,4 @@ window.addEventListener('alpine:init', () => { (() => { HamburgerButton.init(); - ProofingCreatePoll.init(); })(); From 71ffc300eabcad840823e936ff14c0ee61af0e70 Mon Sep 17 00:00:00 2001 From: Ashwin Ramaswami Date: Thu, 8 Sep 2022 22:39:47 -0400 Subject: [PATCH 10/12] Delete proofing-create-poll.js --- ambuda/static/js/proofing-create-poll.js | 20 -------------------- 1 file changed, 20 deletions(-) delete mode 100644 ambuda/static/js/proofing-create-poll.js diff --git a/ambuda/static/js/proofing-create-poll.js b/ambuda/static/js/proofing-create-poll.js deleted file mode 100644 index fa7f5fe4..00000000 --- a/ambuda/static/js/proofing-create-poll.js +++ /dev/null @@ -1,20 +0,0 @@ -import { $, Server } from './core.ts'; - -export default (() => { - // Polls for status on project creation. Used only on - // templates/proofing/create-project-post.html. - function init() { - const $el = document.getElementById('proofing_polling_task_id'); - if (!$el) { - return; - } - const taskId = JSON.parse($el.innerText); - setInterval(() => { - Server.getText(`/proofing/status/${taskId}`, (text) => { - $('#progress').innerHTML = text; - }); - }, 5000); - } - - return { init }; -})(); From 46a69a10c7e9d7061951c07197eb4a87a4cc5330 Mon Sep 17 00:00:00 2001 From: Ashwin Ramaswami Date: Thu, 8 Sep 2022 22:40:18 -0400 Subject: [PATCH 11/12] Update main.js --- ambuda/static/js/main.js | 1 - 1 file changed, 1 deletion(-) diff --git a/ambuda/static/js/main.js b/ambuda/static/js/main.js index 23caec5e..a1b1f68a 100644 --- a/ambuda/static/js/main.js +++ b/ambuda/static/js/main.js @@ -6,7 +6,6 @@ import HamburgerButton from './hamburger-button'; import HTMLPoller from './html-poller'; import Reader from './reader'; import Proofer from './proofer'; -import HamburgerButton from './hamburger-button'; import SortableList from './sortable-list'; window.addEventListener('alpine:init', () => { From 6dd92ed0500cd8812e1e01b97268889786260075 Mon Sep 17 00:00:00 2001 From: Ashwin Ramaswami Date: Thu, 22 Sep 2022 15:02:15 -0400 Subject: [PATCH 12/12] Update proofer.test.js --- test/js/proofer.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/js/proofer.test.js b/test/js/proofer.test.js index 8d2b3dab..274844e2 100644 --- a/test/js/proofer.test.js +++ b/test/js/proofer.test.js @@ -5,12 +5,12 @@ const sampleHTML = `
+ `; // Can't modify existing `window.location` -- delete it so that we can mock it. // (See beforeEach and the tests below.) delete window.location; -window.IMAGE_URL = 'IMAGE_URL'; window.OpenSeadragon = (_) => ({ addHandler: jest.fn((_, callback) => callback()), viewport: {