geovisio 2.6.0__py3-none-any.whl → 2.7.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- geovisio/__init__.py +36 -7
- geovisio/admin_cli/cleanup.py +2 -2
- geovisio/admin_cli/db.py +1 -4
- geovisio/config_app.py +40 -1
- geovisio/db_migrations.py +24 -3
- geovisio/templates/main.html +13 -13
- geovisio/templates/viewer.html +3 -3
- geovisio/translations/de/LC_MESSAGES/messages.mo +0 -0
- geovisio/translations/de/LC_MESSAGES/messages.po +804 -0
- geovisio/translations/el/LC_MESSAGES/messages.mo +0 -0
- geovisio/translations/el/LC_MESSAGES/messages.po +685 -0
- geovisio/translations/en/LC_MESSAGES/messages.mo +0 -0
- geovisio/translations/en/LC_MESSAGES/messages.po +738 -0
- geovisio/translations/es/LC_MESSAGES/messages.mo +0 -0
- geovisio/translations/es/LC_MESSAGES/messages.po +778 -0
- geovisio/translations/fi/LC_MESSAGES/messages.mo +0 -0
- geovisio/translations/fi/LC_MESSAGES/messages.po +589 -0
- geovisio/translations/fr/LC_MESSAGES/messages.mo +0 -0
- geovisio/translations/fr/LC_MESSAGES/messages.po +814 -0
- geovisio/translations/hu/LC_MESSAGES/messages.mo +0 -0
- geovisio/translations/hu/LC_MESSAGES/messages.po +773 -0
- geovisio/translations/ko/LC_MESSAGES/messages.mo +0 -0
- geovisio/translations/ko/LC_MESSAGES/messages.po +685 -0
- geovisio/translations/messages.pot +694 -0
- geovisio/translations/nl/LC_MESSAGES/messages.mo +0 -0
- geovisio/translations/nl/LC_MESSAGES/messages.po +602 -0
- geovisio/utils/__init__.py +1 -1
- geovisio/utils/auth.py +50 -11
- geovisio/utils/db.py +65 -0
- geovisio/utils/excluded_areas.py +83 -0
- geovisio/utils/extent.py +30 -0
- geovisio/utils/fields.py +1 -1
- geovisio/utils/filesystems.py +0 -1
- geovisio/utils/link.py +14 -0
- geovisio/utils/params.py +20 -0
- geovisio/utils/pictures.py +110 -88
- geovisio/utils/reports.py +171 -0
- geovisio/utils/sequences.py +262 -126
- geovisio/utils/tokens.py +37 -42
- geovisio/utils/upload_set.py +642 -0
- geovisio/web/auth.py +37 -37
- geovisio/web/collections.py +304 -304
- geovisio/web/configuration.py +14 -0
- geovisio/web/docs.py +276 -15
- geovisio/web/excluded_areas.py +377 -0
- geovisio/web/items.py +169 -112
- geovisio/web/map.py +104 -36
- geovisio/web/params.py +69 -26
- geovisio/web/pictures.py +14 -31
- geovisio/web/reports.py +399 -0
- geovisio/web/rss.py +13 -7
- geovisio/web/stac.py +129 -134
- geovisio/web/tokens.py +98 -109
- geovisio/web/upload_set.py +771 -0
- geovisio/web/users.py +100 -73
- geovisio/web/utils.py +28 -9
- geovisio/workers/runner_pictures.py +241 -207
- {geovisio-2.6.0.dist-info → geovisio-2.7.1.dist-info}/METADATA +17 -14
- geovisio-2.7.1.dist-info/RECORD +70 -0
- {geovisio-2.6.0.dist-info → geovisio-2.7.1.dist-info}/WHEEL +1 -1
- geovisio-2.6.0.dist-info/RECORD +0 -41
- {geovisio-2.6.0.dist-info → geovisio-2.7.1.dist-info}/LICENSE +0 -0
geovisio/web/users.py
CHANGED
|
@@ -1,20 +1,23 @@
|
|
|
1
1
|
import flask
|
|
2
|
-
from flask import request, current_app
|
|
3
|
-
from
|
|
2
|
+
from flask import request, current_app, url_for
|
|
3
|
+
from flask_babel import gettext as _
|
|
4
|
+
from geovisio.utils import auth, db
|
|
4
5
|
from geovisio import errors
|
|
5
|
-
import psycopg
|
|
6
6
|
from psycopg.rows import dict_row
|
|
7
7
|
from psycopg.sql import SQL
|
|
8
8
|
|
|
9
|
+
from geovisio.web import stac
|
|
10
|
+
from geovisio.web.utils import get_root_link
|
|
11
|
+
|
|
9
12
|
bp = flask.Blueprint("user", __name__, url_prefix="/api/users")
|
|
10
13
|
|
|
11
14
|
|
|
12
15
|
def _get_user_info(id, name):
|
|
13
16
|
userMapUrl = (
|
|
14
|
-
flask.url_for("map.getUserTile", userId=id, x="
|
|
15
|
-
.replace("
|
|
16
|
-
.replace("
|
|
17
|
-
.replace("
|
|
17
|
+
flask.url_for("map.getUserTile", userId=id, x="11111111", y="22222222", z="33333333", format="mvt", _external=True)
|
|
18
|
+
.replace("11111111", "{x}")
|
|
19
|
+
.replace("22222222", "{y}")
|
|
20
|
+
.replace("33333333", "{z}")
|
|
18
21
|
)
|
|
19
22
|
response = {
|
|
20
23
|
"id": id,
|
|
@@ -76,12 +79,11 @@ def getUserInfo(userId):
|
|
|
76
79
|
schema:
|
|
77
80
|
$ref: '#/components/schemas/GeoVisioUser'
|
|
78
81
|
"""
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
raise errors.InvalidAPIUsage("Impossible to find user", status_code=404)
|
|
82
|
+
account = db.fetchone(current_app, SQL("SELECT name, id FROM accounts WHERE id = %s"), [userId], row_factory=dict_row)
|
|
83
|
+
if not account:
|
|
84
|
+
raise errors.InvalidAPIUsage(_("Impossible to find user"), status_code=404)
|
|
83
85
|
|
|
84
|
-
|
|
86
|
+
return _get_user_info(account["id"], account["name"])
|
|
85
87
|
|
|
86
88
|
|
|
87
89
|
@bp.route("/me/catalog")
|
|
@@ -155,14 +157,11 @@ def searchUser():
|
|
|
155
157
|
q = request.args.get("q")
|
|
156
158
|
# for the moment, we can only search by string
|
|
157
159
|
if not q:
|
|
158
|
-
raise errors.InvalidAPIUsage("No search parameter given, you should provide `q=<pattern>` as query parameter", status_code=400)
|
|
160
|
+
raise errors.InvalidAPIUsage(_("No search parameter given, you should provide `q=<pattern>` as query parameter"), status_code=400)
|
|
159
161
|
|
|
160
162
|
limit = request.args.get("limit", default=20, type=int)
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
res = cursor.execute(
|
|
164
|
-
SQL(
|
|
165
|
-
"""
|
|
163
|
+
query = SQL(
|
|
164
|
+
"""
|
|
166
165
|
WITH ranked AS (
|
|
167
166
|
SELECT name, id, similarity({q}, name) AS similarity from accounts
|
|
168
167
|
)
|
|
@@ -171,29 +170,30 @@ WHERE similarity > 0.1
|
|
|
171
170
|
ORDER BY similarity DESC
|
|
172
171
|
LIMIT {limit};
|
|
173
172
|
"""
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
173
|
+
).format(limit=limit, q=q)
|
|
174
|
+
res = db.fetchall(current_app, query, row_factory=dict_row)
|
|
175
|
+
|
|
176
|
+
return {
|
|
177
|
+
"features": [
|
|
178
|
+
{
|
|
179
|
+
"label": r["name"],
|
|
180
|
+
"id": r["id"],
|
|
181
|
+
"links": [
|
|
182
|
+
{
|
|
183
|
+
"rel": "user-info",
|
|
184
|
+
"type": "application/json",
|
|
185
|
+
"href": flask.url_for("user.getUserInfo", userId=r["id"], _external=True),
|
|
186
|
+
},
|
|
187
|
+
{
|
|
188
|
+
"rel": "collection",
|
|
189
|
+
"type": "application/json",
|
|
190
|
+
"href": flask.url_for("stac_collections.getUserCollection", userId=r["id"], _external=True),
|
|
191
|
+
},
|
|
192
|
+
],
|
|
193
|
+
}
|
|
194
|
+
for r in res
|
|
195
|
+
]
|
|
196
|
+
}
|
|
197
197
|
|
|
198
198
|
|
|
199
199
|
@bp.route("/")
|
|
@@ -213,35 +213,62 @@ def listUsers():
|
|
|
213
213
|
|
|
214
214
|
# no pagination yet, can be done when needed
|
|
215
215
|
limit = min(request.args.get("limit", default=1000, type=int), 1000)
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
216
|
+
query = SQL(
|
|
217
|
+
"""SELECT
|
|
218
|
+
a.id, a.name, l.has_seq
|
|
219
|
+
FROM accounts a
|
|
220
|
+
LEFT OUTER JOIN LATERAL (
|
|
221
|
+
SELECT 1 as has_seq
|
|
222
|
+
FROM sequences s
|
|
223
|
+
WHERE s.account_id = a.id
|
|
224
|
+
LIMIT 1
|
|
225
|
+
) l ON true
|
|
226
|
+
ORDER BY created_at
|
|
227
|
+
LIMIT {limit};"""
|
|
228
|
+
).format(limit=limit)
|
|
229
|
+
res = db.fetchall(current_app, query, row_factory=dict_row)
|
|
230
|
+
return {
|
|
231
|
+
"stac_version": stac.STAC_VERSION,
|
|
232
|
+
"id": "geovisio:users",
|
|
233
|
+
"title": "users catalog",
|
|
234
|
+
"description": "List of users catalog",
|
|
235
|
+
"type": "Catalog",
|
|
236
|
+
"conformsTo": stac.CONFORMANCE_LIST,
|
|
237
|
+
"users": [
|
|
238
|
+
{
|
|
239
|
+
"name": r["name"],
|
|
240
|
+
"id": r["id"],
|
|
241
|
+
"links": [
|
|
242
|
+
{
|
|
243
|
+
"rel": "user-info",
|
|
244
|
+
"type": "application/json",
|
|
245
|
+
"href": flask.url_for("user.getUserInfo", userId=r["id"], _external=True),
|
|
246
|
+
},
|
|
247
|
+
{
|
|
248
|
+
"rel": "collection",
|
|
249
|
+
"type": "application/json",
|
|
250
|
+
"href": flask.url_for("stac_collections.getUserCollection", userId=r["id"], _external=True),
|
|
251
|
+
},
|
|
252
|
+
],
|
|
253
|
+
}
|
|
254
|
+
for r in res
|
|
255
|
+
],
|
|
256
|
+
"links": [
|
|
257
|
+
{
|
|
258
|
+
"rel": "user-search",
|
|
259
|
+
"type": "application/json",
|
|
260
|
+
"href": flask.url_for("user.searchUser", _external=True),
|
|
261
|
+
"title": "Search users",
|
|
262
|
+
},
|
|
263
|
+
get_root_link(),
|
|
264
|
+
]
|
|
265
|
+
+ [
|
|
266
|
+
{
|
|
267
|
+
"rel": "child",
|
|
268
|
+
"title": f'User "{r["name"]}" sequences',
|
|
269
|
+
"href": url_for("stac_collections.getUserCollection", userId=r["id"], _external=True),
|
|
270
|
+
}
|
|
271
|
+
for r in res
|
|
272
|
+
if r["has_seq"]
|
|
273
|
+
],
|
|
274
|
+
}
|
geovisio/web/utils.py
CHANGED
|
@@ -2,11 +2,13 @@ import typing
|
|
|
2
2
|
from dateutil import tz
|
|
3
3
|
from datetime import timezone
|
|
4
4
|
from dateutil.tz import gettz
|
|
5
|
-
from
|
|
6
|
-
from functools import wraps
|
|
7
|
-
import psycopg
|
|
8
|
-
from flask import current_app, url_for, Response, make_response
|
|
5
|
+
from functools import wraps, cache
|
|
9
6
|
from geovisio import errors
|
|
7
|
+
from geovisio.utils import db
|
|
8
|
+
from flask import current_app, url_for
|
|
9
|
+
from flask_babel import gettext as _
|
|
10
|
+
from geovisio import __version__
|
|
11
|
+
import subprocess
|
|
10
12
|
|
|
11
13
|
STAC_VERSION = "1.0.0"
|
|
12
14
|
|
|
@@ -44,11 +46,10 @@ def accountIdOrDefault(account):
|
|
|
44
46
|
# Get default account ID
|
|
45
47
|
if account is not None:
|
|
46
48
|
return account.id
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
return str(accountId[0])
|
|
49
|
+
accountId = db.fetchone(current_app, "SELECT id FROM accounts WHERE is_default")
|
|
50
|
+
if accountId is None:
|
|
51
|
+
raise errors.InternalError(_("No default account defined, please contact your instance administrator"))
|
|
52
|
+
return str(accountId[0])
|
|
52
53
|
|
|
53
54
|
|
|
54
55
|
def get_license_link():
|
|
@@ -85,6 +86,24 @@ def get_viewerpage_url():
|
|
|
85
86
|
return url_for("viewer", _external=True)
|
|
86
87
|
|
|
87
88
|
|
|
89
|
+
@cache
|
|
90
|
+
def get_api_version():
|
|
91
|
+
"""
|
|
92
|
+
Retrieve complete API version.
|
|
93
|
+
|
|
94
|
+
Format can be:
|
|
95
|
+
- 2.6.0-99-abcdefgh (release + amount of commits since last tag + commit short SHA) if Git repo is not on a release tag
|
|
96
|
+
- 2.6.0 (release) if Git repo is on release tag (or no Git repo available)
|
|
97
|
+
"""
|
|
98
|
+
|
|
99
|
+
if current_app.config.get("API_GIT_VERSION") is not None:
|
|
100
|
+
return current_app.config["API_GIT_VERSION"]
|
|
101
|
+
try:
|
|
102
|
+
return subprocess.check_output(["git", "describe"]).strip().decode("utf-8")
|
|
103
|
+
except Exception:
|
|
104
|
+
return __version__
|
|
105
|
+
|
|
106
|
+
|
|
88
107
|
def user_dependant_response(flag):
|
|
89
108
|
"""Set if a response is user dependant.
|
|
90
109
|
|