Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
02ac4d4
Upgrade FE to fix security:
MarcelGeo Sep 28, 2026
2eae99f
Fix inconsistent error code
varmar05 Sep 29, 2026
80c58aa
Make password reset tokens single-use
varmar05 Sep 29, 2026
129040b
Merge pull request #684 from MerginMaps/fix_inconsistent_error_code
MarcelGeo Sep 29, 2026
2bfb070
Add v2 endpoint to create project in workspace
harminius Sep 29, 2026
da4a2bd
Merge pull request #683 from MerginMaps/frontend-security-upgrades
MarcelGeo Sep 30, 2026
a296090
Drop public flag from v2 project creation
harminius Sep 30, 2026
fe4e869
Merge pull request #689 from MerginMaps/feat/issue-3549-v2-create-pro…
MarcelGeo Sep 30, 2026
9992d45
Upgrade necesssary beackend deps:
MarcelGeo Sep 30, 2026
e01dccc
Run tests when server files are changed
MarcelGeo Sep 30, 2026
fc15e00
Run the code styles just when files are changed.
MarcelGeo Sep 30, 2026
634f3be
Address review comments
varmar05 Oct 1, 2026
52c141c
increase default token expiration
varmar05 Oct 1, 2026
9070262
Merge pull request #687 from MerginMaps/fix_token_lifetime
MarcelGeo Oct 1, 2026
b5cbd37
Merge pull request #690 from MerginMaps/upgrade-backend-deps
MarcelGeo Oct 1, 2026
19e0b5e
List all unsupported file names in v2 push error
harminius Oct 1, 2026
867d843
Collect unsupported file names in the existing validation loop
harminius Oct 2, 2026
7ae6004
Merge pull request #691 from MerginMaps/feat/issue-3529-unsupported-f…
MarcelGeo Oct 2, 2026
a09cb73
Fix add target uer id
MarcelGeo Oct 2, 2026
e4027c3
Merge pull request #692 from MerginMaps/fix-canceled-audit
MarcelGeo Oct 2, 2026
b09fa5a
Revert chunks lookup to legacy /chunks location
MarcelGeo Oct 2, 2026
d294397
Add target_email field for new superadmin audit event
harminius Oct 5, 2026
b90fa14
Merge branch 'develop' into revert-chunks-dir-fallback
MarcelGeo Oct 5, 2026
72fee6a
Remove spaces
MarcelGeo Oct 5, 2026
f6ea229
Merge pull request #693 from MerginMaps/revert-chunks-dir-fallback
MarcelGeo Oct 5, 2026
0501ce8
Merge pull request #694 from MerginMaps/fix/issue-3545-audit-missing-…
MarcelGeo Oct 5, 2026
fcafaf4
Invalidate sessions and bearer tokens on password change/reset
varmar05 Oct 7, 2026
038d0a2
Merge pull request #695 from MerginMaps/invalidate_tokens_on_reset
MarcelGeo Oct 7, 2026
bfdb839
Decrease bcrypt rounds in tests to speed up runtime
varmar05 Oct 8, 2026
1b65ef1
Share app and db schema across tests to speed up test suite
varmar05 Oct 9, 2026
677d960
Run tests in parallel with pytest-xdist
varmar05 Oct 9, 2026
99109d5
Merge pull request #696 from MerginMaps/speedup-tests
MarcelGeo Oct 12, 2026
4fdb484
Merge branch 'master' into develop
varmar05 Oct 12, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 10 additions & 4 deletions .github/workflows/auto_tests.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
name: Auto Tests

on: push
on:
push:
paths:
# Run just when the backend changed
- "server/**"
- "!server/**/*.md"
- ".github/workflows/auto_tests.yml"

jobs:
tests:
Expand All @@ -11,7 +17,7 @@ jobs:
matrix:
include:
- suite: server
pytest_args: "-v --cov=mergin --cov-report=lcov mergin/tests"
pytest_args: "-v -n auto --cov=mergin --cov-report=lcov mergin/tests"
- suite: migration
pytest_args: "-v mergin/test_migrations"

Expand Down Expand Up @@ -44,8 +50,8 @@ jobs:
run: |
cd server
sudo apt-get -y install libsqlite3-mod-spatialite
pip install pipenv==2026.0.3
pipenv install --dev --verbose --python 3.12
pip install pipenv==2026.8.0
pipenv install --dev --deploy --verbose --python 3.12

- name: Run tests
run: |
Expand Down
21 changes: 6 additions & 15 deletions .github/workflows/code_style.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
name: Code Layout

on: push
on:
push:
paths:
# Run just when python files changed
- "server/**/*.py"
- ".github/workflows/code_style.yml"

jobs:
code_style_python:
Expand All @@ -14,17 +19,3 @@ jobs:
version: 25.1.0
options: "--check --verbose --diff"
src: "./server"

code_style_js:
name: JavaScript code convention check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v4
with:
node-version: '22'
- name: Check JS
run: |
cd web-app
yarn install
yarn run lint:no-legacy
23 changes: 23 additions & 0 deletions .github/workflows/code_style_js.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
name: Code Layout JS

on:
push:
paths:
# Run just when the web app changed
- "web-app/**"
- ".github/workflows/code_style_js.yml"

jobs:
code_style_js:
name: JavaScript code convention check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v4
with:
node-version: '22'
- name: Check JS
run: |
cd web-app
yarn install
yarn run lint:no-legacy
4 changes: 4 additions & 0 deletions deployment/community/.env.template
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ SECRET_KEY=fixme

#BEARER_TOKEN_EXPIRATION=3600 * 12 # in seconds

#PASSWORD_RESET_TOKEN_EXPIRATION=900 # in seconds

#SECURITY_BEARER_SALT=NODEFAULT
SECURITY_BEARER_SALT=fixme

Expand All @@ -73,6 +75,8 @@ SECURITY_UNLOCK_SALT=fixme

#WTF_CSRF_TIME_LIMIT=3600 * 24 # in seconds

#PERMANENT_SESSION_LIFETIME=3600 * 24 * 31 # in seconds, lifetime of web session cookie


# Mail configuration

Expand Down
4 changes: 4 additions & 0 deletions deployment/enterprise/.env.template
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ SECRET_KEY=fixme

#BEARER_TOKEN_EXPIRATION=3600 * 12 # in seconds

#PASSWORD_RESET_TOKEN_EXPIRATION=900 # in seconds

#SECURITY_BEARER_SALT=NODEFAULT
SECURITY_BEARER_SALT=fixme

Expand All @@ -78,6 +80,8 @@ SECURITY_UNLOCK_SALT=fixme

#WTF_CSRF_TIME_LIMIT=3600 * 24 # in seconds

#PERMANENT_SESSION_LIFETIME=3600 * 24 * 31 # in seconds, lifetime of web session cookie


# for flask mail

Expand Down
62 changes: 44 additions & 18 deletions development.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
This page contains useful information for those who wish to develop Mergin.

## Running locally (for dev)

Install dependencies and run services:

### Python and Node.js
Expand All @@ -18,21 +19,28 @@ $ corepack enable # provides yarn
### Postgres and Redis

```shell
$ docker run -d --rm --name mergin_maps_dev_db -p 5002:5432 -e POSTGRES_PASSWORD=postgres postgres:14
$ docker run -d --rm --name mergin_maps_dev_redis -p 6379:6379 redis
docker run -d --rm --name mergin_maps_dev_db -p 5002:5432 -e POSTGRES_PASSWORD=postgres postgres:14
docker run -d --rm --name mergin_maps_dev_redis -p 6379:6379 redis
```

### Server

The server requires **Python 3.12** (see `python_version` in `server/Pipfile`). If your system Python is a different version, use a separate environment, e.g. conda / miniforge or pyenv:

```shell
# conda / miniforge
conda create -n mergin python=3.12
conda activate mergin
# or pyenv
pyenv install 3.12
pyenv local 3.12
```

Pipenv then creates its own virtualenv on top of that interpreter.

```shell
$ pip3 install --upgrade pip==24.0
$ pip3 install pipenv==2024.0.1
$ pip install pipenv==2026.8.0
$ cd server
# Install dependencies with pipenv
# Note: You can append --three flag in older versions of pipenv (< 3.16.8 2023-02-04)
$ pipenv install --dev
$ pipenv install --categories telemetry
$ pipenv run pre-commit install
$ pipenv run pre-commit run --all-files
# dev settings, secrets and salts have no defaults
# not named .env on purpose: pipenv and flask would load it automatically, also into tests
$ cat > .dev.env <<EOF
Expand All @@ -48,13 +56,25 @@ MERGIN_BASE_URL=http://localhost:8080
EOF
# let pipenv load it for commands in this shell
$ export PIPENV_DOTENV_LOCATION=$PWD/.dev.env

# folder for project files (LOCAL_PROJECTS default)
$ mkdir -p ../projects

# Install dependencies with pipenv
$ pipenv install --dev --deploy
$ pipenv install --categories telemetry
$ pipenv run pre-commit install
$ pipenv run pre-commit run --all-files

# initialize DB
$ export FLASK_APP=application; export COLLECT_STATISTICS=0
$ pipenv run flask init-db
# create admin user
$ pipenv run flask user create admin topsecret --is-admin --email admin@example.com
# create (non admin) user
$ pipenv run flask user create user topsecret --email user@example.com

# run dev server and celery worker
$ pipenv run celery -A application.celery worker --loglevel=info &
$ pipenv run flask run # run dev server on port 5000
```
Expand All @@ -64,12 +84,12 @@ $ pipenv run flask run # run dev server on port 5000
Before installing the web applications, make sure you have Node.js installed in a supported version. The applications require Node.js version **22 or higher**.

```shell
$ cd web-app
$ yarn install
$ yarn link:dependencies # link dependencies
$ yarn build:libs # bild libraries @mergin/lib @mergin/admin-lib @mergin/lib-vue2
$ yarn dev # development client web application dev server on port 8080 (package @mergin/app)
$ yarn dev:admin # development admin application dev server on port 8081 (package @mergin/admin-app)
cd web-app
yarn install
yarn link:dependencies # link dependencies
yarn build:libs # bild libraries @mergin/lib @mergin/admin-lib @mergin/lib-vue2
yarn dev # development client web application dev server on port 8080 (package @mergin/app)
yarn dev:admin # development admin application dev server on port 8081 (package @mergin/admin-app)
```

If you are developing a library package (named **-lib*), it is useful to watch the library for changes instead of rebuilding it each time.
Expand All @@ -85,7 +105,6 @@ yarn watch:lib:types

Watching the type definitions is also useful to pick up any changes to imports or new components that are added.


## Running locally in a docker composition

If you want to run the whole stack locally, you can use the docker. Docker will build the images from your local files and run the services.
Expand Down Expand Up @@ -122,6 +141,7 @@ docker exec -it merginmaps-server flask server send-check-email --email admin@e
In docker-compose.dev.yml is started maildev/maildev image that can be used to test emails (see [https://github.com/maildev/maildev/](https://github.com/maildev/maildev/)). In localhost:1080 you can see the emails sent by the application in web interface.

### Running with remote debugger

If you want to run the application with remote debugger, you can use debug compose file with attached source code and reload.
It starts a debugpy session on port 5678 you can attach to.

Expand All @@ -130,11 +150,17 @@ docker compose -f docker-compose.yml -f docker-compose.debug.yml up
```

## Running tests

To launch the unit tests run:

```shell
$ docker run -d --rm --name testing_pg -p 5435:5432 -e POSTGRES_PASSWORD=postgres postgres:14
$ cd server
$ pipenv install --dev --sequential --verbose
$ pipenv install --dev --deploy --verbose
# tests use .test.env only, do not load dev settings (e.g. exported PIPENV_DOTENV_LOCATION)
$ PIPENV_DONT_LOAD_ENV=1 pipenv run pytest -v --cov=mergin mergin/tests
```

Tests can run in parallel with [pytest-xdist](https://pytest-xdist.readthedocs.io), e.g. `pipenv run pytest -n 4 mergin/tests`.
Each worker uses its own database (`<DB_DATABASE>_gw<N>`, created automatically) and its own temporary directory.
To run several test sessions at the same time, give each a different `DB_DATABASE`, e.g. `DB_DATABASE=ce pipenv run pytest -n 4 mergin/tests`.
3 changes: 2 additions & 1 deletion server/.test.env
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,5 @@ SECURITY_PASSWORD_SALT='password'
SECURITY_UNLOCK_SALT='unlock'
DIAGNOSTIC_LOGS_DIR=/tmp/diagnostic_logs
GEVENT_WORKER=0
OTEL_ENABLED=0
OTEL_ENABLED=0
BCRYPT_LOG_ROUNDS=4
2 changes: 1 addition & 1 deletion server/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ WORKDIR /app

# keep installing to system packages
ENV PIP_BREAK_SYSTEM_PACKAGES=1
RUN pip install pipenv==2026.0.3
RUN pip install pipenv==2026.8.0
# for locale check this http://click.pocoo.org/5/python3/
ENV LC_ALL=C.UTF-8
ENV LANG=C.UTF-8
Expand Down
27 changes: 15 additions & 12 deletions server/Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,17 @@ name = "pypi"

[packages]
connexion = {extras = ["swagger-ui"],version = "==2.15.1"}
flask = "==3.1.2"
flask = "==3.1.3"
python-dateutil = "==2.8.2"
marshmallow = "==3.26.1"
marshmallow = "==3.26.2"
flask-marshmallow = "==0.15.0"
marshmallow-sqlalchemy = "==1.4.1"
psycopg2-binary = "==2.9.9"
itsdangerous = "==2.2.0"
Flask-SQLAlchemy = "==3.1.1"
sqlalchemy = "==2.0.44"
gunicorn = {extras = ["gevent"],version = "==23.0"}
python-dotenv = "==0.20.0"
python-dotenv = "==1.2.2"
flask-login = "==0.6.3"
bcrypt = "==4.2.0"
wtforms = {extras = ["email"],version = "==3.2.1"}
Expand All @@ -35,34 +35,37 @@ jsons = "==1.6.3"
binaryornot = "==0.4.4"
chardet = "<5"
python-decouple = "==3.6"
urllib3 = "==2.2.2"
urllib3 = "==2.7.0"
shapely = "==2.0.6"
psycogreen = "==1.0.2"
importlib-metadata = "==8.4.0" # https://github.com/pallets/flask/issues/4502
typing_extensions = "==4.12.2"
python-magic = "==0.4.27"
click = "==8.2.0"
click = "==8.3.3"
# requirements for development on windows
colorama = "==0.4.5"

[dev-packages]
pytest = "==8.3.2"
pytest = "==9.1.1"
pytest-cov = "==5.0.0"
pylint = "==3.2.6"
responses = "==0.21.0"
pytest-dotenv= "==0.5.2"
pysqlite3-binary= "==0.5.3"
pytest-xdist = "==3.8.0"
# sqlite with loadable extensions for tests, pysqlite3-binary wheels are available only for linux
pysqlite3-binary = {version = "==0.5.3", markers = "sys_platform == 'linux'"}
pysqlite3 = {version = "==0.6.0", markers = "sys_platform != 'linux'"}
black = "==25.1.0"
pre-commit = "==4.1.0"
# requirements for pytest on windows
atomicwrites = "==1.4.0"

[telemetry]
opentelemetry-distro = {extras = ["otlp"], version = "*"}
opentelemetry-instrumentation-flask = "*"
opentelemetry-instrumentation-celery = "*"
opentelemetry-instrumentation-sqlalchemy = "*"
opentelemetry-instrumentation-logging = "*"
opentelemetry-distro = {extras = ["otlp"], version = "==0.60b1"}
opentelemetry-instrumentation-flask = "==0.60b1"
opentelemetry-instrumentation-celery = "==0.60b1"
opentelemetry-instrumentation-sqlalchemy = "==0.60b1"
opentelemetry-instrumentation-logging = "==0.60b1"

[requires]
python_version = "3.12"
Loading
Loading