From 7f1f6f4df5252aefbe65d5e269b78e0e3ecfd0c2 Mon Sep 17 00:00:00 2001 From: Leo Bazan Date: Mon, 26 Jun 2023 21:41:21 -0300 Subject: [PATCH 1/8] Add SSL/HTTPS support on dev mode --- README.md | 2 ++ config/dev.exs | 17 +++++++---------- priv/cert/selfsigned.pem | 22 ++++++++++++++++++++++ priv/cert/selfsigned_key.pem | 28 ++++++++++++++++++++++++++++ 4 files changed, 59 insertions(+), 10 deletions(-) create mode 100644 priv/cert/selfsigned.pem create mode 100644 priv/cert/selfsigned_key.pem diff --git a/README.md b/README.md index 11e4d69..716e569 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,8 @@ BOOKMARK_ARCHIVE_DELAY=1000 $ docker login -u bookmarkorg -p ``` +4. Optional: You can use HTTPS on localhost in port 4001. If you are using Google Chrome, open `chrome://flags/#allow-insecure-localhost` to enable the use of self-signed certificates on localhost. + ## Basic Commands: Development Run the app: diff --git a/config/dev.exs b/config/dev.exs index b37fc8c..841155f 100644 --- a/config/dev.exs +++ b/config/dev.exs @@ -39,16 +39,13 @@ config :bookmark, BookmarkWeb.Endpoint, # # Note that this task requires Erlang/OTP 20 or later. # Run `mix help phx.gen.cert` for more information. -# -# The `http:` config above can be replaced with: -# -# https: [ -# port: 4001, -# cipher_suite: :strong, -# keyfile: "priv/cert/selfsigned_key.pem", -# certfile: "priv/cert/selfsigned.pem" -# ], -# +config :bookmark, BookmarkWeb.Endpoint, + https: [ + port: 4001, + cipher_suite: :strong, + keyfile: "priv/cert/selfsigned_key.pem", + certfile: "priv/cert/selfsigned.pem" + ] # If desired, both `http:` and `https:` keys can be # configured to run both http and https servers on # different ports. diff --git a/priv/cert/selfsigned.pem b/priv/cert/selfsigned.pem new file mode 100644 index 0000000..928ed2d --- /dev/null +++ b/priv/cert/selfsigned.pem @@ -0,0 +1,22 @@ +-----BEGIN CERTIFICATE----- +MIIDfDCCAmSgAwIBAgIIfq3YHHWBHR8wDQYJKoZIhvcNAQELBQAwQzEaMBgGA1UE +CgwRUGhvZW5peCBGcmFtZXdvcmsxJTAjBgNVBAMMHFNlbGYtc2lnbmVkIHRlc3Qg +Y2VydGlmaWNhdGUwHhcNMjMwNjI2MDAwMDAwWhcNMjQwNjI2MDAwMDAwWjBDMRow +GAYDVQQKDBFQaG9lbml4IEZyYW1ld29yazElMCMGA1UEAwwcU2VsZi1zaWduZWQg +dGVzdCBjZXJ0aWZpY2F0ZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +AL3eFZsvAiEnbhEwaS+RqppkyTQpwADD/U97qPYt4BFjC3lOHBfh+aamwrkaBvpL +eGbvnlm77ihP2sqSPNwstEKcyBR7xJleif3EX0NOE2b8SHZVx420NznUoHdfnwUa +fa7TkzhoTiGA7wdsnipWV+9Cn0U4v/sWqUTxvjXYQLT3UAaUITd7QiZLjZu8/sP5 +cK1sjx3J/NjrM1jXjYwcHLpFj7cG0P4nF4wZqBnudKb2zB2A4bJ/lGvlhUF/5GeA +cXoCk4n+gDvVHOX1ucyU0vtP5GhsJAVBsiURQJfMZxAF6jKrlxKUMlSlAZyX3FCp +XjWrsKsK+RkxcttAYyq4PoECAwEAAaN0MHIwDAYDVR0TAQH/BAIwADAOBgNVHQ8B +Af8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMB0GA1UdDgQW +BBTZmMlASFS8Lwu3hBQRJm9qUF9fyTAUBgNVHREEDTALgglsb2NhbGhvc3QwDQYJ +KoZIhvcNAQELBQADggEBAI4K2dvGkSJjum6vnnk+y9843KsAh3mjLloMFUmZ/lox +0tpNO48Z+eWcj6Qepd92cVv80wDsykLRvKVG1DNgI0XfrCD9CL1TvH9gDQU07113 +S+S6yTcQnMZ/5Krj7ZcMrnqI1w8elqJE1AbrubOvfizU00Yk5ppU28X1QTz+NU0D +NvQS6jlpaX48Id52/bhRp4p3ne/1nH+7IT+1WGA7paLcoAfxm7KVX28DDKScU6iP +mw0/+h7TYenbOTjRnaxW6R92fE3l6ViLbInTUN0okCqUnnF3ptV4WO6ATOkxnuPu +kCTMDuA0qC9ho69t9nwLSTMuW28RH7Kcp6mX8xr56GI= +-----END CERTIFICATE----- + diff --git a/priv/cert/selfsigned_key.pem b/priv/cert/selfsigned_key.pem new file mode 100644 index 0000000..b3dee27 --- /dev/null +++ b/priv/cert/selfsigned_key.pem @@ -0,0 +1,28 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpQIBAAKCAQEAvd4Vmy8CISduETBpL5GqmmTJNCnAAMP9T3uo9i3gEWMLeU4c +F+H5pqbCuRoG+kt4Zu+eWbvuKE/aypI83Cy0QpzIFHvEmV6J/cRfQ04TZvxIdlXH +jbQ3OdSgd1+fBRp9rtOTOGhOIYDvB2yeKlZX70KfRTi/+xapRPG+NdhAtPdQBpQh +N3tCJkuNm7z+w/lwrWyPHcn82OszWNeNjBwcukWPtwbQ/icXjBmoGe50pvbMHYDh +sn+Ua+WFQX/kZ4BxegKTif6AO9Uc5fW5zJTS+0/kaGwkBUGyJRFAl8xnEAXqMquX +EpQyVKUBnJfcUKleNauwqwr5GTFy20BjKrg+gQIDAQABAoIBAAvUkC0Ur0HIlquc +hBlSLrqjCARni46gp6JxtpPsRNdggAEFdGuqiWcwYdatv/yNgkmLqaa2tn6thxjz +JrajVHIIGdFo6tWRlfCJcVQcw8m5c3xoGOCD96LzVDJL83kabvVbOoObwC6HPZ2N +T4eczKrcUFc8U33+KfrhQzRQrqt31/qrg6H5WWTbHJqzecfJJ3Mp797s3QmsA5KI +8CC9o/BmzlaCYbllnw/mk0H4qMMqqyyNILjArvnusHyh3CvvEKD1DyG2PD6g5XZ/ +m21Brg6e8v5JkKP1vjhFLio4jp8/dOBf2eraoik4o1OmZ9BUWdZQ+eE8SPak6nwA +FlMPJU8CgYEA2LHR6QM7w7XKN4mPsw4uUrsNa/kTy72hIBY1lLRUMB5SfPdKt6Nc +rOAFk4H6SfRFIiDmzEMzm3h1VdfeTfCgcM9+WqDn7vvFYqqji4wRABvM34Dztrg0 +k4O+jdQ0/UvgwiEIoENf7C7jVAm2uXTVdRMXHuNhbZ1HFyeNHvh5MX8CgYEA4E6N +eif2L0dhHYkA2Ug2jhzqLzhZyYHJUsN2dD1S9lrkU2Ux2ZyIP6IaFsDle3yYgOD3 +qi1qBMLPizQySqbxxYv5Wv9iHPdksyd5jjWpo2WbrlgPdHI8CGe/UKiGtzvJXl7D +k55tWn/7YeMkH8Wn9CB97POBKL/paOdaeaGmj/8CgYEA0q4gbjIMmz1V/CUsp2P0 +Oc9PP1kNnBskWrP9KDUjXR0+Ce3MoTqdUh8EjOPkWp650HK4soPr2w6E1g9pPdHj +y4qRSMAEf+Adis5o77YgmUBuMieHzHDP/VQrom1dj5+ESHohjt+ylUkJEJ3ZH/qt +xoPnCMr94Lr3cVWs6R2fhzUCgYEAjt25gsqdJPPjyToPzlUOWmnURwsvNQdzQUG5 +2sOMadjugKd9nsryhQUsdL2b7JEpWTzwwfV3B11Fb7ZpKd83Msm6otjyltyDyRAl +fgxz5dy70cnI3jQ8RGZAFpGgbGiqE29sRkOsBu5pIKnZwlrUZMulKRzXcSr68ZQZ +rkrlmeUCgYEAz4kIiJQN4rzJexUfUoE4cHFKBAUzo4ghnqs3rcgV+w8zBdgIgqQF +s56jly1rthZEBDL9jN45toDnb2sT+DihgwtBOwE05TV33WMSHwMHDxcpUM557iKT +vaa1Hbek4aAUPg70TQYBuk4oylYrZm8ySYHtt0kSCf/zsV0KEI9Mdlk= +-----END RSA PRIVATE KEY----- + From 791b6e0edf1009f2a9055374121bc09469ce1448 Mon Sep 17 00:00:00 2001 From: Leo Bazan Date: Mon, 26 Jun 2023 18:07:39 -0300 Subject: [PATCH 2/8] CSS: Fix text overflow in buttons --- assets/css/app.css | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/assets/css/app.css b/assets/css/app.css index e758c24..454f64b 100644 --- a/assets/css/app.css +++ b/assets/css/app.css @@ -32,13 +32,16 @@ } .donate-button { - height: 66px; + height: auto; + line-height: 1.5; font-size: 23px; font-weight: bold; border-radius: 10px; color: #ce0000; background-color: black; - border: 1px solid white; + border: 1px solid white; + white-space: normal; + word-wrap: break-word; } .go-button { From 6de214f522bec38b2c1dcdddfd76c6be9d9f675b Mon Sep 17 00:00:00 2001 From: Leo Bazan Date: Mon, 26 Jun 2023 22:38:39 -0300 Subject: [PATCH 3/8] UI -> Withdraw QR: Show QR button only if the camera is enabled + Responsive --- assets/css/app.css | 11 +++++++++++ assets/js/app.js | 13 ++++++++++++- lib/bookmark_web/live/withdrawals.ex | 4 ++-- 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/assets/css/app.css b/assets/css/app.css index 454f64b..c003ae1 100644 --- a/assets/css/app.css +++ b/assets/css/app.css @@ -970,3 +970,14 @@ body { } +/******************************************** Withdraw *****************************************/ + +@media screen and (max-width: 350px) { + .donate-button.scan{ width: auto; } + .donate-button.withdraw{ width: auto; margin-top: 50px;} +} + +@media screen and (min-width: 350px) { + .donate-button.scan{ width: auto; margin-bottom: 10px; padding-left: auto;} + .donate-button.withdraw{ width: 100%;} +} diff --git a/assets/js/app.js b/assets/js/app.js index 6290f1d..46d700d 100644 --- a/assets/js/app.js +++ b/assets/js/app.js @@ -29,9 +29,20 @@ import QrScanner from "../vendor/qr-scanner.min.js" let Hooks = {}; Hooks.ScanCode = { - mounted() { + async mounted() { const btn = document.getElementById("scan-btn"); + if (await QrScanner.hasCamera()) { + showScanButton(); + } + + function showScanButton() { + var scanButton = document.getElementById('scan-btn'); + scanButton.removeAttribute('hidden'); + var withdrawButton = document.getElementById('withdraw-btn'); + withdrawButton.style.width = '66%'; + } + btn.addEventListener("click", () => { this.pushEvent("scan-btn-clicked"); }); diff --git a/lib/bookmark_web/live/withdrawals.ex b/lib/bookmark_web/live/withdrawals.ex index 3aaf61e..be80133 100644 --- a/lib/bookmark_web/live/withdrawals.ex +++ b/lib/bookmark_web/live/withdrawals.ex @@ -20,8 +20,8 @@ defmodule BookmarkWeb.WithdrawalsLive do
- - + +
<%= if @show_modal do %> From 33a6cb4ac6b18564d5472c70264408f7159f0e2d Mon Sep 17 00:00:00 2001 From: Leo Bazan Date: Tue, 27 Jun 2023 18:50:41 -0300 Subject: [PATCH 4/8] Add Nginx and Certbot to Prod env --- .gitignore | 3 ++ data/nginx/app.conf | 27 +++++++++++++++ docker-compose.yml | 14 ++++++++ init-letsencrypt.sh | 84 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 128 insertions(+) create mode 100644 data/nginx/app.conf create mode 100755 init-letsencrypt.sh diff --git a/.gitignore b/.gitignore index 252a571..2f57b2e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,9 @@ # Env file .env +# Certbot files +/data/certbot/ + # The directory Mix will write compiled artifacts to. /_build/ diff --git a/data/nginx/app.conf b/data/nginx/app.conf new file mode 100644 index 0000000..be69bde --- /dev/null +++ b/data/nginx/app.conf @@ -0,0 +1,27 @@ +server { + listen 80; + server_name alpha.bookmark.org; + location / { + return 301 https://$host$request_uri; + } + + location /.well-known/acme-challenge/ { + root /var/www/certbot; + } +} + +server { + listen 443 ssl; + server_name alpha.bookmark.org; + + location / { + proxy_pass http://alpha.bookmark.org; + } + + ssl_certificate /etc/letsencrypt/live/alpha.bookmark.org/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/alpha.bookmark.org/privkey.pem; + + include /etc/letsencrypt/options-ssl-nginx.conf; + ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; +} + diff --git a/docker-compose.yml b/docker-compose.yml index 15197cb..1cc7639 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,5 +1,19 @@ version: "3.9" services: + nginx: + image: nginx:1.15-alpine + ports: + - "80:80" + - "443:443" + volumes: + - ./data/nginx:/etc/nginx/conf.d + + certbot: + image: certbot/certbot + volumes: + - ./data/certbot/conf:/etc/letsencrypt + - ./data/certbot/www:/var/www/certbot + bookmark: image: bookmarkorg/bookmark:latest container_name: bookmark-app diff --git a/init-letsencrypt.sh b/init-letsencrypt.sh new file mode 100755 index 0000000..0c25c2a --- /dev/null +++ b/init-letsencrypt.sh @@ -0,0 +1,84 @@ +#!/bin/bash + +# IMPORTANT: +# Don't forget to check and configure the `domains` and `email` variables before running this script. +# You can run it, with `chmod +x init-letsencrypt.sh` and `sudo ./init-letsencrypt.sh` + +if ! [ -x "$(command -v docker)" ]; then + echo 'Error: docker compose is not installed.' >&2 + exit 1 +fi + +domains=(alpha.bookmark.org) +rsa_key_size=4096 +data_path="./data/certbot" +email="" # Adding a valid address is strongly recommended +staging=0 # Set to 1 if you're testing your setup to avoid hitting request limits + +if [ -d "$data_path" ]; then + read -p "Existing data found for $domains. Continue and replace existing certificate? (y/N) " decision + if [ "$decision" != "Y" ] && [ "$decision" != "y" ]; then + exit + fi +fi + + +if [ ! -e "$data_path/conf/options-ssl-nginx.conf" ] || [ ! -e "$data_path/conf/ssl-dhparams.pem" ]; then + echo "### Downloading recommended TLS parameters ..." + mkdir -p "$data_path/conf" + curl -s https://raw.githubusercontent.com/certbot/certbot/master/certbot-nginx/certbot_nginx/_internal/tls_configs/options-ssl-nginx.conf > "$data_path/conf/options-ssl-nginx.conf" + curl -s https://raw.githubusercontent.com/certbot/certbot/master/certbot/certbot/ssl-dhparams.pem > "$data_path/conf/ssl-dhparams.pem" + echo +fi + +echo "### Creating dummy certificate for $domains ..." +path="/etc/letsencrypt/live/$domains" +mkdir -p "$data_path/conf/live/$domains" +docker compose run --rm --entrypoint "\ + openssl req -x509 -nodes -newkey rsa:$rsa_key_size -days 1\ + -keyout '$path/privkey.pem' \ + -out '$path/fullchain.pem' \ + -subj '/CN=localhost'" certbot +echo + + +echo "### Starting nginx ..." +docker compose up --force-recreate -d nginx +echo + +echo "### Deleting dummy certificate for $domains ..." +docker compose run --rm --entrypoint "\ + rm -Rf /etc/letsencrypt/live/$domains && \ + rm -Rf /etc/letsencrypt/archive/$domains && \ + rm -Rf /etc/letsencrypt/renewal/$domains.conf" certbot +echo + + +echo "### Requesting Let's Encrypt certificate for $domains ..." +#Join $domains to -d args +domain_args="" +for domain in "${domains[@]}"; do + domain_args="$domain_args -d $domain" +done + +# Select appropriate email arg +case "$email" in + "") email_arg="--register-unsafely-without-email" ;; + *) email_arg="--email $email" ;; +esac + +# Enable staging mode if needed +if [ $staging != "0" ]; then staging_arg="--staging"; fi + +docker compose run --rm --entrypoint "\ + certbot certonly --webroot -w /var/www/certbot \ + $staging_arg \ + $email_arg \ + $domain_args \ + --rsa-key-size $rsa_key_size \ + --agree-tos \ + --force-renewal" certbot +echo + +echo "### Reloading nginx ..." +docker compose exec nginx nginx -s reload From 1471dd76e5a9fc1e2ac4579c30afe40bb1ed2c7b Mon Sep 17 00:00:00 2001 From: Leo Bazan Date: Tue, 27 Jun 2023 20:50:27 -0300 Subject: [PATCH 5/8] Fix Nginx config --- data/nginx/app.conf | 4 ++-- docker-compose.yml | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/data/nginx/app.conf b/data/nginx/app.conf index be69bde..4fb65c0 100644 --- a/data/nginx/app.conf +++ b/data/nginx/app.conf @@ -21,7 +21,7 @@ server { ssl_certificate /etc/letsencrypt/live/alpha.bookmark.org/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/alpha.bookmark.org/privkey.pem; - include /etc/letsencrypt/options-ssl-nginx.conf; - ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; + # include /etc/letsencrypt/options-ssl-nginx.conf; + # ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; } diff --git a/docker-compose.yml b/docker-compose.yml index 1cc7639..e6a0419 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -7,6 +7,8 @@ services: - "443:443" volumes: - ./data/nginx:/etc/nginx/conf.d + - ./data/certbot/conf:/etc/letsencrypt + - ./data/certbot/www:/var/www/certbot certbot: image: certbot/certbot @@ -26,7 +28,7 @@ services: - bookmark-db - archivebox ports: - - '80:4000' + - '4000:4000' env_file: - base.env volumes: From a265f9af56b4a769a248200db4709a9891a78804 Mon Sep 17 00:00:00 2001 From: Leo Bazan Date: Wed, 28 Jun 2023 19:39:03 -0300 Subject: [PATCH 6/8] Auto update Let's encrypt certificates --- data/nginx/app.conf | 27 +++++++++++++++++---------- docker-compose.yml | 2 ++ 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/data/nginx/app.conf b/data/nginx/app.conf index 4fb65c0..132b169 100644 --- a/data/nginx/app.conf +++ b/data/nginx/app.conf @@ -1,27 +1,34 @@ +upstream bookmark { + server bookmark-app:4000; +} + server { listen 80; + listen [::]:80; + server_name alpha.bookmark.org; - location / { - return 301 https://$host$request_uri; - } + server_tokens off; location /.well-known/acme-challenge/ { root /var/www/certbot; } + + location / { + return 301 https://$host$request_uri; + } } server { - listen 443 ssl; - server_name alpha.bookmark.org; + listen 443 default_server ssl http2; + listen [::]:443 ssl http2; - location / { - proxy_pass http://alpha.bookmark.org; - } + server_name alpha.bookmark.org; ssl_certificate /etc/letsencrypt/live/alpha.bookmark.org/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/alpha.bookmark.org/privkey.pem; - # include /etc/letsencrypt/options-ssl-nginx.conf; - # ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; + location / { + proxy_pass http://bookmark; + } } diff --git a/docker-compose.yml b/docker-compose.yml index e6a0419..e2475ae 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -2,6 +2,7 @@ version: "3.9" services: nginx: image: nginx:1.15-alpine + command: "/bin/sh -c 'while :; do sleep 6h & wait $${!}; nginx -s reload; done & nginx -g \"daemon off;\"'" ports: - "80:80" - "443:443" @@ -12,6 +13,7 @@ services: certbot: image: certbot/certbot + entrypoint: "/bin/sh -c 'trap exit TERM; while :; do certbot renew; sleep 12h & wait $${!}; done;'" volumes: - ./data/certbot/conf:/etc/letsencrypt - ./data/certbot/www:/var/www/certbot From f90e1d989f38e2e74c6adf6fe9ca9ecd9d32f07c Mon Sep 17 00:00:00 2001 From: Leo Bazan Date: Wed, 28 Jun 2023 20:19:07 -0300 Subject: [PATCH 7/8] Fix websocket using https in production --- data/nginx/app.conf | 3 +++ docker-compose.yml | 1 + 2 files changed, 4 insertions(+) diff --git a/data/nginx/app.conf b/data/nginx/app.conf index 132b169..20bb2fe 100644 --- a/data/nginx/app.conf +++ b/data/nginx/app.conf @@ -29,6 +29,9 @@ server { location / { proxy_pass http://bookmark; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "Upgrade"; } } diff --git a/docker-compose.yml b/docker-compose.yml index e2475ae..2e47f09 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -25,6 +25,7 @@ services: environment: OPENAI_API_KEY: ${OPENAI_API_KEY} BOOKMARK_ARCHIVE_DELAY: ${BOOKMARK_ARCHIVE_DELAY} + PHX_HOST: alpha.bookmark.org MIX_ENV: prod depends_on: - bookmark-db From 28e1c704922a61627cd6085148c722a64a46707b Mon Sep 17 00:00:00 2001 From: Leo Bazan Date: Wed, 28 Jun 2023 21:34:23 -0300 Subject: [PATCH 8/8] Withdraw: Fix getting link from QR --- assets/js/app.js | 4 +++- lib/bookmark/withdrawals.ex | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/assets/js/app.js b/assets/js/app.js index 46d700d..6af48ec 100644 --- a/assets/js/app.js +++ b/assets/js/app.js @@ -54,7 +54,9 @@ Hooks.ScanCode = { video, result => { qrScanner.stop(); - this.pushEvent("modal-closed", result); + qr_data = result["data"] + console.log("QR data: ", qr_data) + this.pushEvent("modal-closed", qr_data); }, { highlightScanRegion: true, highlightCodeOutline: true, diff --git a/lib/bookmark/withdrawals.ex b/lib/bookmark/withdrawals.ex index a296823..7c7dd95 100644 --- a/lib/bookmark/withdrawals.ex +++ b/lib/bookmark/withdrawals.ex @@ -13,7 +13,7 @@ defmodule Bookmark.Withdrawals do headers: [{:x_api_key, key}], method: :post, body: body, - receive_timeout: 30_000 + receive_timeout: 60_000 ) do {:ok, response} -> case response.status do