diff --git a/aleph.env.tmpl b/aleph.env.tmpl index e265972722..9c29ba9087 100644 --- a/aleph.env.tmpl +++ b/aleph.env.tmpl @@ -17,9 +17,6 @@ ALEPH_UI_URL=http://localhost:8080/ # ALEPH_FAVICON=https://investigativedashboard.org/static/favicon.ico # ALEPH_LOGO=http://assets.pudo.org/img/logo_bigger.png -# Other customisations -ALEPH_SAMPLE_SEARCHES=Vladimir Putin:TeliaSonera - # Set email addresses, separated by colons, that will be made admin. # ALEPH_ADMINS=friedrich@pudo.org:demo@pudo.org diff --git a/aleph/model/role.py b/aleph/model/role.py index ccc3ff66c2..3b7e3a3649 100644 --- a/aleph/model/role.py +++ b/aleph/model/role.py @@ -177,7 +177,7 @@ def by_api_key(cls, api_key): return q.first() @classmethod - def load_or_create(cls, foreign_id, type_, name, email=None, is_admin=None): + def load_or_create(cls, foreign_id, type_, name, email=None, is_admin=False): role = cls.by_foreign_id(foreign_id) if role is None: @@ -185,7 +185,7 @@ def load_or_create(cls, foreign_id, type_, name, email=None, is_admin=None): role.foreign_id = foreign_id role.name = name or email role.type = type_ - role.is_admin = False + role.is_admin = is_admin role.is_muted = False role.is_tester = False role.is_blocked = False @@ -197,14 +197,6 @@ def load_or_create(cls, foreign_id, type_, name, email=None, is_admin=None): if email is not None: role.email = email - if is_admin is not None: - role.is_admin = is_admin - - # see: https://github.com/alephdata/aleph/issues/111 - auto_admins = [a.lower() for a in settings.ADMINS] - if email is not None and email.lower() in auto_admins: - role.is_admin = True - db.session.add(role) db.session.flush() return role diff --git a/aleph/oauth.py b/aleph/oauth.py index bf22592f77..0112a75d4f 100644 --- a/aleph/oauth.py +++ b/aleph/oauth.py @@ -1,10 +1,10 @@ import logging -from pprint import pformat # noqa from authlib.jose import JsonWebToken, JsonWebKey from authlib.integrations.flask_client import OAuth from authlib.jose.errors import DecodeError from aleph import settings +from aleph.util import is_auto_admin oauth = OAuth() log = logging.getLogger(__name__) @@ -92,7 +92,7 @@ def handle_oauth(provider, oauth_token): role.foreign_id = role_id role.update({"name": name}) if role is None: - role = Role.load_or_create(role_id, Role.USER, name, email=email) + role = Role.load_or_create(role_id, Role.USER, name, email=email, is_admin=is_auto_admin(email)) if not role.is_actor: return None role.clear_roles() diff --git a/aleph/tests/test_view_util.py b/aleph/tests/test_view_util.py index 508585309f..a5afb28533 100644 --- a/aleph/tests/test_view_util.py +++ b/aleph/tests/test_view_util.py @@ -1,7 +1,10 @@ +import json + from lxml.html import document_fromstring +from werkzeug.exceptions import BadRequest from aleph.logic.html import sanitize_html -from aleph.views.util import get_url_path +from aleph.views.util import get_url_path, validate from aleph.tests.util import TestCase @@ -32,3 +35,25 @@ def test_sanitize_html(self): assert attr == "https://example.org/blockchain", html assert html.find(".//a").get("target") == "_blank", html assert "nofollow" in html.find(".//a").get("rel"), html + + def test_validate_returns_errors_for_paths(self): + # given + schema = "RoleCreate" # name min length 4, password min length 6 + data = json.loads('{"name":"Bob","password":"1234","code":"token"}') + + # then + with self.assertRaises(BadRequest) as ctx: + validate(data, schema) + + self.assertEqual(ctx.exception.response.get_json().get("errors"), {"name": "'Bob' is too short", "password": "'1234' is too short"}) + + def test_validate_concatenates_multiple_errors_for_the_same_path(self): + # given + schema = "RoleCreate" # requires password and code + data = json.loads('{"wrong":"No password, no code"}') + + # then + with self.assertRaises(BadRequest) as ctx: + validate(data, schema) + + self.assertEqual(ctx.exception.response.get_json().get("errors"), {"": "'password' is a required property; 'code' is a required property"}) diff --git a/aleph/translations/bs/LC_MESSAGES/aleph.po b/aleph/translations/bs/LC_MESSAGES/aleph.po index 85047f74f7..2bf21a4115 100644 --- a/aleph/translations/bs/LC_MESSAGES/aleph.po +++ b/aleph/translations/bs/LC_MESSAGES/aleph.po @@ -14,7 +14,11 @@ msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" +<<<<<<< HEAD +"POT-Creation-Date: 2022-03-24 13:21+0100\n" +======= "POT-Creation-Date: 2022-03-28 10:50+0200\n" +>>>>>>> main "PO-Revision-Date: 2018-03-15 07:37+0000\n" "Last-Translator: Tajna Biscevic , 2019\n" "Language-Team: Bosnian (https://www.transifex.com/aleph/teams/76591/bs/)\n" diff --git a/aleph/translations/de/LC_MESSAGES/aleph.po b/aleph/translations/de/LC_MESSAGES/aleph.po index ca1fcffbff..dc9f27a299 100644 --- a/aleph/translations/de/LC_MESSAGES/aleph.po +++ b/aleph/translations/de/LC_MESSAGES/aleph.po @@ -11,7 +11,11 @@ msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" +<<<<<<< HEAD +"POT-Creation-Date: 2022-03-24 13:21+0100\n" +======= "POT-Creation-Date: 2022-03-28 10:50+0200\n" +>>>>>>> main "PO-Revision-Date: 2018-03-15 07:37+0000\n" "Last-Translator: pudo , 2020\n" "Language-Team: German (https://www.transifex.com/aleph/teams/76591/de/)\n" diff --git a/aleph/translations/es/LC_MESSAGES/aleph.po b/aleph/translations/es/LC_MESSAGES/aleph.po index 2b388aaaec..058961610c 100644 --- a/aleph/translations/es/LC_MESSAGES/aleph.po +++ b/aleph/translations/es/LC_MESSAGES/aleph.po @@ -13,7 +13,11 @@ msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" +<<<<<<< HEAD +"POT-Creation-Date: 2022-03-24 13:21+0100\n" +======= "POT-Creation-Date: 2022-03-28 10:50+0200\n" +>>>>>>> main "PO-Revision-Date: 2018-03-15 07:37+0000\n" "Last-Translator: Nathan Jaccard , 2020\n" "Language-Team: Spanish (https://www.transifex.com/aleph/teams/76591/es/)\n" diff --git a/aleph/translations/fr/LC_MESSAGES/aleph.po b/aleph/translations/fr/LC_MESSAGES/aleph.po index ce46766c1d..9cfa4a9b5f 100644 --- a/aleph/translations/fr/LC_MESSAGES/aleph.po +++ b/aleph/translations/fr/LC_MESSAGES/aleph.po @@ -12,7 +12,11 @@ msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" +<<<<<<< HEAD +"POT-Creation-Date: 2022-03-24 13:21+0100\n" +======= "POT-Creation-Date: 2022-03-28 10:50+0200\n" +>>>>>>> main "PO-Revision-Date: 2018-03-15 07:37+0000\n" "Last-Translator: Jean-Philippe Menotti, 2022\n" "Language-Team: French (https://www.transifex.com/aleph/teams/76591/fr/)\n" diff --git a/aleph/translations/messages.pot b/aleph/translations/messages.pot index 739ea4287f..cffeee2f73 100644 --- a/aleph/translations/messages.pot +++ b/aleph/translations/messages.pot @@ -8,7 +8,11 @@ msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" +<<<<<<< HEAD +"POT-Creation-Date: 2022-03-24 13:21+0100\n" +======= "POT-Creation-Date: 2022-03-28 10:50+0200\n" +>>>>>>> main "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" diff --git a/aleph/translations/pt_BR/LC_MESSAGES/aleph.po b/aleph/translations/pt_BR/LC_MESSAGES/aleph.po index 99c0a805f7..7c2641d2a7 100644 --- a/aleph/translations/pt_BR/LC_MESSAGES/aleph.po +++ b/aleph/translations/pt_BR/LC_MESSAGES/aleph.po @@ -11,7 +11,11 @@ msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" +<<<<<<< HEAD +"POT-Creation-Date: 2022-03-24 13:21+0100\n" +======= "POT-Creation-Date: 2022-03-28 10:50+0200\n" +>>>>>>> main "PO-Revision-Date: 2018-03-15 07:37+0000\n" "Last-Translator: Laura M , 2019\n" "Language-Team: Portuguese (Brazil) (https://www.transifex.com/aleph/teams/76591/pt_BR/)\n" diff --git a/aleph/translations/ru/LC_MESSAGES/aleph.po b/aleph/translations/ru/LC_MESSAGES/aleph.po index bd289bb94f..603e95b559 100644 --- a/aleph/translations/ru/LC_MESSAGES/aleph.po +++ b/aleph/translations/ru/LC_MESSAGES/aleph.po @@ -11,7 +11,11 @@ msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" +<<<<<<< HEAD +"POT-Creation-Date: 2022-03-24 13:21+0100\n" +======= "POT-Creation-Date: 2022-03-28 10:50+0200\n" +>>>>>>> main "PO-Revision-Date: 2018-03-15 07:37+0000\n" "Last-Translator: jen occrp, 2021\n" "Language-Team: Russian (https://www.transifex.com/aleph/teams/76591/ru/)\n" diff --git a/aleph/translations/tr/LC_MESSAGES/aleph.po b/aleph/translations/tr/LC_MESSAGES/aleph.po index 47a7f88f53..8b3359c559 100644 --- a/aleph/translations/tr/LC_MESSAGES/aleph.po +++ b/aleph/translations/tr/LC_MESSAGES/aleph.po @@ -11,7 +11,11 @@ msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" +<<<<<<< HEAD +"POT-Creation-Date: 2022-03-24 13:21+0100\n" +======= "POT-Creation-Date: 2022-03-28 10:50+0200\n" +>>>>>>> main "PO-Revision-Date: 2018-03-15 07:37+0000\n" "Last-Translator: Pinar Dag , 2018\n" "Language-Team: Turkish (https://www.transifex.com/aleph/teams/76591/tr/)\n" diff --git a/aleph/util.py b/aleph/util.py index 8429cf03a1..126582e6cb 100644 --- a/aleph/util.py +++ b/aleph/util.py @@ -1,5 +1,6 @@ import json import structlog +from aleph import settings from datetime import datetime, date from normality import stringify from flask_babel.speaklater import LazyString @@ -82,3 +83,7 @@ def perform_request(self, method, url, headers=None, params=None, body=None): del payload["es_req_body"] log.debug("Performed ES request", **payload) return result + +def is_auto_admin(email): + auto_admins = [a.lower() for a in settings.ADMINS] + return email is not None and email.lower() in auto_admins diff --git a/aleph/views/roles_api.py b/aleph/views/roles_api.py index 4aaba3ebd3..9f3a42871b 100644 --- a/aleph/views/roles_api.py +++ b/aleph/views/roles_api.py @@ -10,6 +10,7 @@ from aleph.search import QueryParser, DatabaseQueryResult from aleph.model import Role from aleph.logic.roles import challenge_role, update_role, create_user, get_deep_role +from aleph.util import is_auto_admin from aleph.views.serializers import RoleSerializer from aleph.views.util import require, jsonify, parse_request, obj_or_404 from aleph.views.context import tag_request @@ -146,7 +147,7 @@ def create(): status=409, ) - role = create_user(email, data.get("name"), data.get("password")) + role = create_user(email, data.get("name"), data.get("password"), is_admin=is_auto_admin(email)) # Let the serializer return more info about this user request.authz = Authz.from_role(role) tag_request(role_id=role.id) diff --git a/aleph/views/util.py b/aleph/views/util.py index f1153dedb5..eb51273e3e 100644 --- a/aleph/views/util.py +++ b/aleph/views/util.py @@ -59,11 +59,13 @@ def parse_request(schema): def validate(data, schema): """Validate the data inside a request against a schema.""" validator = get_validator(schema) - # data = clean_object(data) errors = {} for error in validator.iter_errors(data): path = ".".join((str(c) for c in error.path)) - errors[path] = error.message + if path not in errors: + errors[path] = error.message + else: + errors[path] += '; ' + error.message log.info("ERROR [%s]: %s", path, error.message) if not len(errors): diff --git a/contrib/aleph-traefik-minio-keycloak/.dockerignore b/contrib/aleph-traefik-minio-keycloak/.dockerignore new file mode 100644 index 0000000000..f1421ffe94 --- /dev/null +++ b/contrib/aleph-traefik-minio-keycloak/.dockerignore @@ -0,0 +1,14 @@ +build +ui +helm +aleph.env +aleph.egg-info +docker-compose.* +celerybeat-schedul* +contrib/allCountries.zip +.git +.vscode +.github +.travis.yml +.env +.tx \ No newline at end of file diff --git a/contrib/aleph-traefik-minio-keycloak/.gitignore b/contrib/aleph-traefik-minio-keycloak/.gitignore new file mode 100644 index 0000000000..27cf2860e3 --- /dev/null +++ b/contrib/aleph-traefik-minio-keycloak/.gitignore @@ -0,0 +1,107 @@ +*.pyc +*.DS_Store +.DS_Store +*.sqlite3 +__pycache__ +balkhashdb + +TODO.md + +build* + +ui/node_modules +ui/build +ui/package-lock.json +ui/i18n/messages.json +ui/i18n/messages.pot +ui/**/*.css + +services/elasticsearch/secrets + +celerybeat-schedule* +aleph.env +test_settings.py +.coverage + +npm-debug.log* +.idea/ +ui/.idea/ +node_modules/* +.eslintcache + +# C extensions +*.so + +# Distribution / packaging +.Python +env/ +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +*.egg-info/ +.installed.cfg +*.egg +.vscode/ + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*,cover +.hypothesis/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# pyenv +.python-version + +# dotenv +.env + +# virtualenv +.venv +venv/ +ENV/ + +# Spyder project settings +.spyderproject + +# Rope project settings +.ropeproject diff --git a/contrib/aleph-traefik-minio-keycloak/LICENSE.txt b/contrib/aleph-traefik-minio-keycloak/LICENSE.txt new file mode 100644 index 0000000000..61e78c4d4d --- /dev/null +++ b/contrib/aleph-traefik-minio-keycloak/LICENSE.txt @@ -0,0 +1,22 @@ +MIT License + +Copyright (c) 2014-2015 Friedrich Lindenberg +Copyright (c) 2016-2020 Journalism Development Network, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/contrib/aleph-traefik-minio-keycloak/README.rst b/contrib/aleph-traefik-minio-keycloak/README.rst new file mode 100644 index 0000000000..e78d866db3 --- /dev/null +++ b/contrib/aleph-traefik-minio-keycloak/README.rst @@ -0,0 +1,28 @@ +Setting up Aleph with Traefik, Minio and keycloak. +-------------------------------------------------- + +Some Tips +--------- + +* Be sure to follow the instructions for a normal install as well as using +these config files. + +* shell into aleph and run 'aleph upgrade' to create the needed database +structures. + +* In the keycloak configuration set HTML Display nameand Frontend URL to +your keycloak dns domain with /auth/ after it. + +* Keycloak account-console under clients needs to be +https://your-auth-domain/auth/realms/aleph-users/account/ + +* Keycloak aleph-ui under clients needs to be https://your-aleph-domain/ + +* Keycloak security-admin-console under clients needs to be https://your-auth-domain/auth/admin/aleph-users/console/ + +* Use minio client on exposed minio port on localhost to create the aleph bucket +if you have trouble with S3. Otherwise leave it alone. + +Misc +---- +There is a start and stop script included. diff --git a/contrib/aleph-traefik-minio-keycloak/docker-compose.yml b/contrib/aleph-traefik-minio-keycloak/docker-compose.yml new file mode 100644 index 0000000000..66274cd3e8 --- /dev/null +++ b/contrib/aleph-traefik-minio-keycloak/docker-compose.yml @@ -0,0 +1,236 @@ +version: "3.3" + +services: + postgres: + image: postgres:13.6 + hostname: postgres + ports: + - "127.0.0.1:15432:5432" + volumes: + - "./DATA/aleph-postgres:/var/lib/postgresql/data" + environment: + POSTGRES_USER: aleph + POSTGRES_PASSWORD: aleph + POSTGRES_DATABASE: aleph + labels: + - "traefik.enable=false" + + elasticsearch: + image: ghcr.io/alephdata/aleph-elasticsearch:3bb5dbed97cfdb9955324d11e5c623a5c5bbc410 + hostname: elasticsearch + environment: + - discovery.type=single-node + ports: + - "127.0.0.1:19200:9200" + volumes: + - "./DATA/elasticsearch-data:/usr/share/elasticsearch/data" + labels: + - "traefik.enable=false" + + redis: + image: redis:alpine + command: [ "redis-server", "--save", "3600", "10" ] + volumes: + - "./DATA/redis-data:/data" + labels: + - "traefik.enable=false" + + convert-document: + image: ghcr.io/alephdata/convert-document:3.16.1 + read_only: true + restart: on-failure + user: app + tmpfs: /tmp + labels: + - "traefik.enable=false" + + ingest-file: + image: ghcr.io/alephdata/ingest-file:3.16.1 + tmpfs: + - /tmp:mode=777 + volumes: + - ./DATA/archive-data:/data + links: + - postgres + - redis + - convert-document + depends_on: + - postgres + - redis + - convert-document + restart: on-failure + env_file: + - aleph.env + labels: + - "traefik.enable=false" + + worker: + image: alephdata/aleph:${ALEPH_TAG:-3.12.2} + command: aleph worker + restart: on-failure + links: + - postgres + - elasticsearch + - redis + - ingest-file + depends_on: + - postgres + - elasticsearch + - redis + - ingest-file + - keycloak-postgres + - keycloak + tmpfs: + - /tmp + volumes: + - "./DATA/archive-data:/data" + env_file: + - aleph.env + labels: + - "traefik.enable=false" + + shell: + image: alephdata/aleph:${ALEPH_TAG:-3.12.2} + command: /bin/bash + depends_on: + - postgres + - elasticsearch + - redis + - ingest-file + - worker + tmpfs: + - /tmp + volumes: + - ./DATA/archive-data:/data + - "./mappings:/aleph/mappings" + - "~:/host" + env_file: + - aleph.env + labels: + - "traefik.enable=false" + + api: + image: alephdata/aleph:${ALEPH_TAG:-3.12.2} + command: gunicorn -w 6 -b 0.0.0.0:8000 --log-level debug --log-file - aleph.wsgi:app + expose: + - 8000 + depends_on: + - postgres + - elasticsearch + - redis + - worker + - ingest-file + - minio + - traefik + tmpfs: + - /tmp + volumes: + - ./DATA/archive-data:/data + env_file: + - aleph.env + labels: + - "traefik.enable=false" + + ui: + image: alephdata/aleph-ui-production:${ALEPH_TAG:-3.12.2} + depends_on: + - api + - traefik + expose: + - 8080 + labels: + - traefik.enable=true + - traefik.http.routers.ui.rule=Host(`your-base-domain`) + - traefik.http.services.ui.loadbalancer.server.port=8080 + - traefik.http.routers.ui.entrypoints=websecure + - traefik.http.routers.ui.tls=true + - traefik.http.routers.ui.tls.certresolver=lets-encrypt + + keycloak-postgres: + image: postgres:13.6 + hostname: keycloak-postgres + ports: + - "127.0.0.1:25432:5432" + volumes: + - "./DATA/keycloak-postgres:/var/lib/postgresql/data" + environment: + POSTGRES_DB: keycloak + POSTGRES_USER: keycloak + POSTGRES_PASSWORD: keycloak + labels: + - "traefik.enable=false" + + keycloak: + image: jboss/keycloak + hostname: keycloak + links: + - keycloak-postgres + volumes: + - "./contrib/keycloak/keycloak-create-realm.sh:/usr/local/bin/keycloak-create-realm.sh" + environment: + DB_VENDOR: POSTGRES + DB_ADDR: keycloak-postgres + DB_DATABASE: keycloak + DB_USER: keycloak + DB_SCHEMA: public + DB_PASSWORD: keycloak + # KEYCLOAK_USER: admin + # KEYCLOAK_PASSWORD: REDACTED + JDBC_PARAMS: "ssl=false" + PROXY_ADDRESS_FORWARDING: "true" + KEYCLOAK_FRONTEND_URL: "https://auth.your-base-domain/auth/" + expose: + - 8080 + labels: + - traefik.enable=true + - traefik.http.routers.keycloak.rule=Host(`auth.your-base-domain`) + - traefik.http.services.keycloak.loadbalancer.server.port=8080 + - traefik.http.routers.keycloak.entrypoints=websecure + - traefik.http.routers.keycloak.tls=true + - traefik.http.routers.keycloak.tls.certresolver=lets-encrypt + + traefik: + image: "traefik:v2.6" + container_name: "traefik" + ports: + - "80:80" + - "443:443" + volumes: + - "/var/run/docker.sock:/var/run/docker.sock:ro" + - "./DATA/LETSENCRYPT/:/letsencrypt" + - "./traefik.toml:/traefik.toml" + - "./traefik_dynamic.toml:/traefik_dynamic.toml" + labels: + - "traefik.enable=true" + + whoami: + image: "traefik/whoami" + container_name: "whoami.your-base-domain" + labels: + - traefik.enable=true + - traefik.http.routers.whoami.rule=Host(`whoami.your-base-domain`) + - traefik.http.routers.whoami.entrypoints=websecure + - traefik.http.routers.whoami.tls=true + - traefik.http.routers.whoami.tls.certresolver=lets-encrypt + + # root user is access_key root password is secret key + minio: + image: 'bitnami/minio:latest' + hostname: minio + ports: + - '127.0.0.1:9000:9000' + - '127.0.0.1:9001:9001' + volumes: + - './DATA/minio_data:/data' + environment: + - MINIO_ROOT_USER=minioadmin + - MINIO_ROOT_PASSWORD=minioadmin + labels: + - "traefik.enable=false" + + +volumes: + archive-data: {} + postgres-data: {} + redis-data: {} + elasticsearch-data: {} diff --git a/contrib/aleph-traefik-minio-keycloak/start.sh b/contrib/aleph-traefik-minio-keycloak/start.sh new file mode 100755 index 0000000000..e09f0923d5 --- /dev/null +++ b/contrib/aleph-traefik-minio-keycloak/start.sh @@ -0,0 +1,5 @@ +#!/bin/sh + +#docker-compose -f docker-compose.yml up -d --scale convert-document=6 --scale worker=6 + +docker-compose -f docker-compose.yml up -d diff --git a/contrib/aleph-traefik-minio-keycloak/stop.sh b/contrib/aleph-traefik-minio-keycloak/stop.sh new file mode 100755 index 0000000000..efe9d3d9c2 --- /dev/null +++ b/contrib/aleph-traefik-minio-keycloak/stop.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +docker-compose -f docker-compose.yml down diff --git a/contrib/aleph-traefik-minio-keycloak/traefik.toml b/contrib/aleph-traefik-minio-keycloak/traefik.toml new file mode 100644 index 0000000000..eb8804f1f4 --- /dev/null +++ b/contrib/aleph-traefik-minio-keycloak/traefik.toml @@ -0,0 +1,24 @@ +[entryPoints] + [entryPoints.web] + address = ":80" + [entryPoints.web.http.redirections.entryPoint] + to = "websecure" + scheme = "https" + + [entryPoints.websecure] + address = ":443" + +[api] + dashboard = true + +[certificatesResolvers.lets-encrypt.acme] + email = "redacted@nowhere.nowhen" + storage = "/letsencrypt/acme.json" + [certificatesResolvers.lets-encrypt.acme.tlsChallenge] + +[providers.docker] + watch = true + network = "web" + +[providers.file] + filename = "traefik_dynamic.toml" diff --git a/contrib/aleph-traefik-minio-keycloak/traefik_dynamic.toml b/contrib/aleph-traefik-minio-keycloak/traefik_dynamic.toml new file mode 100755 index 0000000000..a1b70b8cdf --- /dev/null +++ b/contrib/aleph-traefik-minio-keycloak/traefik_dynamic.toml @@ -0,0 +1,12 @@ +[http.middlewares.simpleAuth.basicAuth] + users = [ + "admin:$aThis-Password-REDACTED-6AM/" + ] + +[http.routers.api] + rule = "Host(`traefik.your-base-domain`)" + entrypoints = ["websecure"] + middlewares = ["simpleAuth"] + service = "api@internal" + [http.routers.api.tls] + certResolver = "lets-encrypt" diff --git a/docker-compose.yml b/docker-compose.yml index ce967d4e1f..df9c19e016 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -81,7 +81,7 @@ services: api: image: alephdata/aleph:${ALEPH_TAG:-3.12.2} - command: gunicorn -w 6 -b 0.0.0.0:8000 --log-level debug --log-file - aleph.wsgi:app + command: gunicorn -w 6 -b 0.0.0.0:8000 --timeout 3600 --log-level debug --log-file - aleph.wsgi:app expose: - 8000 depends_on: diff --git a/requirements.txt b/requirements.txt index e5d150a803..f6661d20ee 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,11 +1,11 @@ # Dependencies maintained by OCCRP banal==1.0.6 -followthemoney==2.8.5 +followthemoney==2.9.3 followthemoney-store[postgresql]==3.0.3 followthemoney-compare==0.4.3 fingerprints==1.0.3 servicelayer[google,amazon]==1.19.0 -normality==2.3.1 +normality==2.3.3 pantomime==0.5.1 # Flask ecosystem @@ -15,23 +15,23 @@ Flask-Mail==0.9.1 Flask-Migrate==3.1.0 Flask-Cors==3.0.10 Flask-Babel==2.0.0 -flask-talisman==0.8.1 -SQLAlchemy==1.4.32 +flask-talisman==1.0.0 +SQLAlchemy==1.4.36 alembic==1.7.7 authlib==0.15.5 elasticsearch==7.17.0 marshmallow==2.19.2 gunicorn[eventlet]==20.1.0 -jsonschema==4.4.0 -apispec==5.1.1 +jsonschema==4.5.1 +apispec==5.2.2 apispec-webframeworks==0.5.2 blinker==1.4 -Babel==2.9.1 +Babel==2.10.1 PyYAML==5.4.1 python-frontmatter==1.0.0 pyjwt >= 2.0.1, < 2.4.0 -cryptography >= 36.0.0, < 37.0.0 +cryptography >= 36.0.0, < 38.0.0 requests[security] >= 2.25.1, < 3.0.0 urllib3==1.26.9 tabulate==0.8.9 diff --git a/ui/package.json b/ui/package.json index 66ee919072..1f847eb8d2 100644 --- a/ui/package.json +++ b/ui/package.json @@ -3,18 +3,18 @@ "version": "3.12.2", "private": true, "dependencies": { - "@alephdata/followthemoney": "2.8.4", + "@alephdata/followthemoney": "2.9.3", "@alephdata/react-ftm": "2.6.0", "@blueprintjs/colors": "^3.0.0", - "@blueprintjs/core": "3.52.0", + "@blueprintjs/core": "3.54.0", "@blueprintjs/icons": "3.31.0", "@blueprintjs/popover2": "^0.12.1", - "@blueprintjs/select": "3.18.11", + "@blueprintjs/select": "3.19.1", "@blueprintjs/table": "3.9.13", "@formatjs/cli": "^4.2.2", "@formatjs/intl-locale": "^2.4.14", "@formatjs/intl-pluralrules": "^4.0.6", - "@formatjs/intl-relativetimeformat": "^9.0.0", + "@formatjs/intl-relativetimeformat": "^10.0.1", "@formatjs/intl-utils": "^3.8.4", "@types/jest": "^27.0.1", "@types/node": "^17.0.8", @@ -80,6 +80,6 @@ ] }, "devDependencies": { - "file-selector": "^0.2.2" + "file-selector": "^0.6.0" } } \ No newline at end of file