Skip to content

Commit 0bddcfa

Browse files
authored
Merge pull request #511 from MerginMaps/master
Backport master -> develop
2 parents f9e7292 + 846a396 commit 0bddcfa

12 files changed

Lines changed: 89 additions & 23 deletions

File tree

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ You are currently browsing repository for Mergin Maps web server and web client.
4747
- 🌱 **Sharing with collaborators** - Projects can be shared with other team members
4848
- 🏰 **Permission system** - Decide who can read, write or manage projects
4949
- 🌈 **Web interface** - Simple user interface to view and manage projects
50-
- ⚡️ **Fast** - Efficient sync protocol transfering data between clients and server
50+
- ⚡️ **Fast** - Efficient sync protocol transferring data between clients and server
5151
- 🧑‍💻 **Developer friendly** - Mergin Maps is open platform. CLI tools and client libraries are available for [Python](https://github.com/MerginMaps/python-api-client) and [C++](https://github.com/MerginMaps/cpp-api-client)
5252
- :camera: **Sync images** - Supporting sync of photos with common cloud storage using [mergin-media-sync](https://github.com/MerginMaps/media-sync) tool
5353
- 💽 **Sync with database** - Supporting two-way sync of data with PostGIS using [mergin-db-sync](https://github.com/MerginMaps/db-sync) tool
@@ -74,7 +74,7 @@ Admin users can enter the admin interface available at `/admin` URL which provid
7474

7575
### Contributing
7676

77-
Contributions are welcomed! You can set up development environment by following a guide in [development.md](./deployment/community/development.md). Before you create your first pull request, we kindly ask you to sign the CLA with your GitHub user name and date [here](LICENSES/CLA-signed-list.md).
77+
Contributions are welcomed! You can set up development environment by following a guide in [development.md](./development.md). Before you create your first pull request, we kindly ask you to sign the CLA with your GitHub user name and date [here](LICENSES/CLA-signed-list.md).
7878

7979
## Documentation
8080

@@ -93,7 +93,7 @@ If you need support, a custom deployment, extending the service capabilities and
9393

9494
Contributions are welcome!
9595

96-
More information for developers can be found in the dedicated [development](./deployment/community/development.md) page.
96+
More information for developers can be found in the dedicated [development](./development.md) page.
9797

9898
Client side modules:
9999
- [Python](https://github.com/MerginMaps/python-api-client) client library + CLI

deployment/community/.env.template

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -98,12 +98,10 @@ MAIL_SUPPRESS_SEND=0
9898

9999
#MAIL_BCC=''
100100

101-
#MERGIN_LOGO_URL= # for link to logo in emails
101+
MERGIN_LOGO_URL=https://merginmaps.com/MM_logo_HORIZ_COLOR_TRANSPARENT_no_padding.png
102102

103103
#MAIL_DEBUG=MAIL_SUPPRESS_SEND | False
104104

105-
106-
107105
# data sync
108106

109107
#LOCAL_PROJECTS=os.path.join(config_dir, os.pardir, os.pardir, 'projects') # for local storage type
@@ -215,5 +213,7 @@ NO_MONKEY_PATCH=False
215213

216214
# Diagnostic logs
217215

216+
DIAGNOSTIC_LOGS_URL=
217+
218218
DIAGNOSTIC_LOGS_DIR=/diagnostic_logs
219219

deployment/community/docker-compose.yml

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ services:
3030
volumes:
3131
- ./projects:/data
3232
- ./diagnostic_logs:/diagnostic_logs
33-
- ../common/entrypoint.sh:/app/entrypoint.sh
3433
env_file:
3534
- .prod.env
3635
depends_on:
@@ -48,8 +47,6 @@ services:
4847
environment:
4948
- GEVENT_WORKER=0
5049
- NO_MONKEY_PATCH=1
51-
volumes:
52-
- ../common/entrypoint.sh:/app/entrypoint.sh
5350
depends_on:
5451
- redis
5552
- server
@@ -68,7 +65,6 @@ services:
6865
- NO_MONKEY_PATCH=1
6966
volumes:
7067
- ./projects:/data
71-
- ../common/entrypoint.sh:/app/entrypoint.sh
7268
depends_on:
7369
- redis
7470
- server

deployment/enterprise/.env.template

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -175,11 +175,8 @@ ACCOUNT_EXPIRATION=1
175175

176176
# for links generated in emails
177177

178-
#MERGIN_BASE_URL=http://localhost:5000
179-
MERGIN_BASE_URL=fixme
180-
181178
#MERGIN_LOGO_URL= # for link to logo in emails
182-
MERGIN_LOGO_URL=fixme
179+
MERGIN_LOGO_URL=https://merginmaps.com/MM_logo_HORIZ_COLOR_TRANSPARENT_no_padding.png
183180

184181
# global workspace related bits - ignored in non-CE versions
185182
# GLOBAL_WORKSPACE mergin
@@ -228,6 +225,8 @@ VECTOR_TILES_STYLE_URL=https://tiles-ee.merginmaps.com//styles/default.json
228225
### Diagnostic logs from Mobile and QGIS Plugin
229226
DIAGNOSTIC_LOGS_DIR=/diagnostic_logs
230227

228+
DIAGNOSTIC_LOGS_URL=
229+
231230
### SSO ################################################################################################################
232231
SSO_ENABLED=False
233232

deployment/enterprise/docker-compose.yml

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,10 @@ services:
1313
volumes:
1414
- ./data:/data # map data dir to host
1515
- ./diagnostic_logs:/diagnostic_logs # diagnostic logs dir
16-
- ../common/entrypoint.sh:/app/entrypoint.sh
1716
env_file:
1817
- .prod.env
18+
environment:
19+
- GUNICORN_CMD_ARGS="--limit-request-line 8190"
1920
depends_on:
2021
- db
2122
networks:
@@ -56,8 +57,6 @@ services:
5657
restart: always
5758
user: 901:999
5859
command: ["celery -A application.celery beat --loglevel=info"]
59-
volumes:
60-
- ../common/entrypoint.sh:/app/entrypoint.sh
6160
env_file:
6261
- .prod.env
6362
depends_on:
@@ -75,7 +74,6 @@ services:
7574
volumes:
7675
- ./data:/data # map data dir to host
7776
- ./map_data:/overviews
78-
- ../common/entrypoint.sh:/app/entrypoint.sh
7977
env_file:
8078
- .prod.env
8179
depends_on:

development.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ $ yarn install
4343
$ yarn link:dependencies # link dependencies
4444
$ yarn build:libs # bild libraries @mergin/lib @mergin/admin-lib @mergin/lib-vue2
4545
$ yarn dev # development client web application dev server on port 8080 (package @mergin/app)
46-
$ yarn dev:admin # development admin appplication dev server on port 8081 (package @mergin/admin-app)
46+
$ yarn dev:admin # development admin application dev server on port 8081 (package @mergin/admin-app)
4747
```
4848

4949
If you are developing a library package (named **-lib*), it is useful to watch the library for changes instead of rebuilding it each time.
@@ -98,7 +98,7 @@ docker exec -it merginmaps-server flask server send-check-email --email admin@e
9898
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.
9999

100100
### Running with remote debugger
101-
If you want to run the application with remote debugger, you can use debug compose file with attatched source code and reload.
101+
If you want to run the application with remote debugger, you can use debug compose file with attached source code and reload.
102102
It starts a debugpy session on port 5678 you can attach to.
103103

104104
```shell

server/mergin/auth/models.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ class User(db.Model):
3636
default=datetime.datetime.utcnow,
3737
)
3838

39+
last_signed_in = db.Column(db.DateTime(), nullable=True)
40+
3941
__table_args__ = (
4042
db.Index("ix_user_username", func.lower(username), unique=True),
4143
db.Index("ix_user_email", func.lower(email), unique=True),
@@ -289,6 +291,7 @@ def __init__(self, user_id: int, ua: str, ip: str, device_id: Optional[str] = No
289291
self.user_agent = ua
290292
self.ip_address = ip
291293
self.device_id = device_id
294+
self.timestamp = datetime.datetime.now(tz=datetime.timezone.utc)
292295

293296
@staticmethod
294297
def add_record(user_id: int, req: request) -> None:
@@ -300,4 +303,37 @@ def add_record(user_id: int, req: request) -> None:
300303
return
301304
lh = LoginHistory(user_id, ua, ip, device_id)
302305
db.session.add(lh)
306+
307+
# cache user last login
308+
User.query.filter_by(id=user_id).update({"last_signed_in": lh.timestamp})
309+
db.session.commit()
310+
311+
@staticmethod
312+
def get_users_last_signed_in(user_ids: list) -> dict:
313+
"""Get users last signed in dates.
314+
Result is also cached in User table for future use.
315+
"""
316+
result = (
317+
db.session.query(
318+
LoginHistory.user_id,
319+
func.max(LoginHistory.timestamp).label("last_signed_in"),
320+
)
321+
.filter(LoginHistory.user_id.in_(user_ids))
322+
.group_by(LoginHistory.user_id)
323+
.all()
324+
)
325+
326+
user_mapping = [
327+
{
328+
"id": row.user_id, # user_id as PK in User table
329+
"last_signed_in": row.last_signed_in,
330+
}
331+
for row in result
332+
]
333+
if not user_mapping:
334+
return {}
335+
336+
# cache users last signed in
337+
db.session.bulk_update_mappings(User, user_mapping)
303338
db.session.commit()
339+
return {item["id"]: item["last_signed_in"] for item in user_mapping}

server/mergin/sync/public_api_controller.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1021,7 +1021,7 @@ def push_finish(transaction_id):
10211021
)
10221022
corrupted_files.append(f.path)
10231023
continue
1024-
if not is_supported_type(dest_file):
1024+
if not f.diff and not is_supported_type(dest_file):
10251025
logging.info(f"Rejecting blacklisted file: {dest_file}")
10261026
abort(
10271027
400,

server/mergin/tests/test_auth.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,15 @@ def test_login(client, data, headers, expected):
7777
)
7878
assert login_history
7979
assert login_history.device_id == str(headers.get("X-Device-Id"))
80+
assert user.last_signed_in == login_history.timestamp
81+
users_last_signed_in = LoginHistory.get_users_last_signed_in([user.id])
82+
assert users_last_signed_in[user.id] == login_history.timestamp
83+
84+
# verify missing value is cached on first LoginHistory access
85+
user.last_signed_in = None
86+
db.session.commit()
87+
users_last_signed_in = LoginHistory.get_users_last_signed_in([user.id])
88+
assert user.last_signed_in == users_last_signed_in[user.id]
8089

8190

8291
def test_logout(client):
@@ -376,6 +385,7 @@ def test_api_login(client, data, headers, expected):
376385
.first()
377386
)
378387
assert login_history
388+
assert user.last_signed_in == login_history.timestamp
379389

380390

381391
def test_api_login_from_urllib(client):
@@ -394,6 +404,8 @@ def test_api_login_from_urllib(client):
394404
.first()
395405
)
396406
assert not login_history
407+
# we do not have recored last login yet
408+
assert user.last_signed_in is None
397409

398410

399411
def test_api_user_profile(client):

server/mergin/version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,4 @@
44

55

66
def get_version():
7-
return "2025.6.2"
7+
return "2025.7.3"

0 commit comments

Comments
 (0)