geovisio 2.9.0__py3-none-any.whl → 2.11.0__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.
Files changed (82) hide show
  1. geovisio/__init__.py +8 -1
  2. geovisio/admin_cli/user.py +7 -2
  3. geovisio/config_app.py +26 -12
  4. geovisio/translations/ar/LC_MESSAGES/messages.mo +0 -0
  5. geovisio/translations/ar/LC_MESSAGES/messages.po +818 -0
  6. geovisio/translations/be/LC_MESSAGES/messages.mo +0 -0
  7. geovisio/translations/be/LC_MESSAGES/messages.po +886 -0
  8. geovisio/translations/br/LC_MESSAGES/messages.po +1 -1
  9. geovisio/translations/da/LC_MESSAGES/messages.mo +0 -0
  10. geovisio/translations/da/LC_MESSAGES/messages.po +96 -4
  11. geovisio/translations/de/LC_MESSAGES/messages.mo +0 -0
  12. geovisio/translations/de/LC_MESSAGES/messages.po +214 -122
  13. geovisio/translations/el/LC_MESSAGES/messages.po +1 -1
  14. geovisio/translations/en/LC_MESSAGES/messages.mo +0 -0
  15. geovisio/translations/en/LC_MESSAGES/messages.po +234 -157
  16. geovisio/translations/eo/LC_MESSAGES/messages.mo +0 -0
  17. geovisio/translations/eo/LC_MESSAGES/messages.po +55 -5
  18. geovisio/translations/es/LC_MESSAGES/messages.po +1 -1
  19. geovisio/translations/fi/LC_MESSAGES/messages.po +1 -1
  20. geovisio/translations/fr/LC_MESSAGES/messages.mo +0 -0
  21. geovisio/translations/fr/LC_MESSAGES/messages.po +92 -3
  22. geovisio/translations/hu/LC_MESSAGES/messages.po +1 -1
  23. geovisio/translations/it/LC_MESSAGES/messages.mo +0 -0
  24. geovisio/translations/it/LC_MESSAGES/messages.po +63 -3
  25. geovisio/translations/ja/LC_MESSAGES/messages.po +1 -1
  26. geovisio/translations/ko/LC_MESSAGES/messages.po +1 -1
  27. geovisio/translations/messages.pot +216 -139
  28. geovisio/translations/nl/LC_MESSAGES/messages.mo +0 -0
  29. geovisio/translations/nl/LC_MESSAGES/messages.po +333 -62
  30. geovisio/translations/oc/LC_MESSAGES/messages.mo +0 -0
  31. geovisio/translations/oc/LC_MESSAGES/messages.po +821 -0
  32. geovisio/translations/pl/LC_MESSAGES/messages.po +1 -1
  33. geovisio/translations/pt/LC_MESSAGES/messages.mo +0 -0
  34. geovisio/translations/pt/LC_MESSAGES/messages.po +944 -0
  35. geovisio/translations/pt_BR/LC_MESSAGES/messages.mo +0 -0
  36. geovisio/translations/pt_BR/LC_MESSAGES/messages.po +942 -0
  37. geovisio/translations/sv/LC_MESSAGES/messages.mo +0 -0
  38. geovisio/translations/sv/LC_MESSAGES/messages.po +4 -3
  39. geovisio/translations/ti/LC_MESSAGES/messages.mo +0 -0
  40. geovisio/translations/ti/LC_MESSAGES/messages.po +762 -0
  41. geovisio/translations/tr/LC_MESSAGES/messages.mo +0 -0
  42. geovisio/translations/tr/LC_MESSAGES/messages.po +927 -0
  43. geovisio/translations/uk/LC_MESSAGES/messages.mo +0 -0
  44. geovisio/translations/uk/LC_MESSAGES/messages.po +920 -0
  45. geovisio/translations/zh_Hant/LC_MESSAGES/messages.po +1 -1
  46. geovisio/utils/annotations.py +21 -21
  47. geovisio/utils/auth.py +47 -13
  48. geovisio/utils/cql2.py +22 -5
  49. geovisio/utils/fields.py +14 -2
  50. geovisio/utils/items.py +44 -0
  51. geovisio/utils/model_query.py +2 -2
  52. geovisio/utils/pic_shape.py +1 -1
  53. geovisio/utils/pictures.py +127 -36
  54. geovisio/utils/semantics.py +32 -3
  55. geovisio/utils/sentry.py +1 -1
  56. geovisio/utils/sequences.py +155 -109
  57. geovisio/utils/upload_set.py +303 -206
  58. geovisio/utils/users.py +18 -0
  59. geovisio/utils/website.py +1 -1
  60. geovisio/web/annotations.py +303 -69
  61. geovisio/web/auth.py +1 -1
  62. geovisio/web/collections.py +194 -97
  63. geovisio/web/configuration.py +36 -4
  64. geovisio/web/docs.py +109 -13
  65. geovisio/web/items.py +319 -186
  66. geovisio/web/map.py +92 -54
  67. geovisio/web/pages.py +48 -4
  68. geovisio/web/params.py +100 -42
  69. geovisio/web/pictures.py +37 -3
  70. geovisio/web/prepare.py +4 -2
  71. geovisio/web/queryables.py +57 -0
  72. geovisio/web/stac.py +8 -2
  73. geovisio/web/tokens.py +49 -1
  74. geovisio/web/upload_set.py +226 -51
  75. geovisio/web/users.py +89 -8
  76. geovisio/web/utils.py +26 -8
  77. geovisio/workers/runner_pictures.py +128 -23
  78. {geovisio-2.9.0.dist-info → geovisio-2.11.0.dist-info}/METADATA +15 -14
  79. geovisio-2.11.0.dist-info/RECORD +117 -0
  80. geovisio-2.9.0.dist-info/RECORD +0 -98
  81. {geovisio-2.9.0.dist-info → geovisio-2.11.0.dist-info}/WHEEL +0 -0
  82. {geovisio-2.9.0.dist-info → geovisio-2.11.0.dist-info}/licenses/LICENSE +0 -0
geovisio/__init__.py CHANGED
@@ -1,6 +1,6 @@
1
1
  """GeoVisio API - Main"""
2
2
 
3
- __version__ = "2.9.0"
3
+ __version__ = "2.11.0"
4
4
 
5
5
  import os
6
6
  from flask import Flask, jsonify, stream_template, send_from_directory, redirect, request, url_for
@@ -31,6 +31,7 @@ from geovisio.web import (
31
31
  prepare,
32
32
  pages,
33
33
  annotations,
34
+ queryables,
34
35
  )
35
36
  from geovisio.workers import runner_pictures
36
37
 
@@ -54,6 +55,11 @@ LOGGING_CONFIG = {
54
55
  },
55
56
  "loggers": {
56
57
  "PIL": {"handlers": ["stdout", "stderr"], "level": "WARN", "propagate": False}, # lower PIL loggers to only have warnings
58
+ "watchdog": {
59
+ "handlers": ["stdout", "stderr"],
60
+ "level": "WARN",
61
+ "propagate": False,
62
+ }, # lower watchdog loggers too (used by flask hot reload)
57
63
  },
58
64
  "root": {"level": "INFO", "handlers": ["stderr", "stdout"]},
59
65
  }
@@ -131,6 +137,7 @@ def create_app(test_config=None, app=None):
131
137
  app.register_blueprint(prepare.bp)
132
138
  app.register_blueprint(pages.bp)
133
139
  app.register_blueprint(annotations.bp)
140
+ app.register_blueprint(queryables.bp)
134
141
 
135
142
  # Register CLI comands
136
143
  app.register_blueprint(admin_cli.bp, cli_group=None)
@@ -6,6 +6,7 @@ from flask.cli import with_appcontext
6
6
  from geovisio.utils import db
7
7
  from geovisio.utils.auth import AccountRole
8
8
  from psycopg.rows import dict_row
9
+ from geovisio.utils.users import delete_user_data
9
10
 
10
11
  bp = Blueprint("user", __name__)
11
12
 
@@ -18,10 +19,11 @@ class Account:
18
19
 
19
20
  @bp.cli.command("user")
20
21
  @click.argument("account_id_or_name")
21
- @click.option("--set-role", required=True, help="Role you want to give to the account. Must be one of: admin or user")
22
+ @click.option("--set-role", help="Role you want to give to the account. Must be one of: admin or user")
22
23
  @click.option("--create", is_flag=True, show_default=True, default=False, help="If provided, create the account if it does not exist")
24
+ @click.option("--delete-data", is_flag=True, show_default=True, default=False, help="If provided, delete all the user's pictures")
23
25
  @with_appcontext
24
- def update_user(account_id_or_name, set_role=None, create=False):
26
+ def update_user(account_id_or_name, set_role=None, create=False, delete_data=False):
25
27
  """
26
28
  Update some information about a user.
27
29
  To identify the account, either the account_id or the account_name must be provided.
@@ -33,6 +35,9 @@ def update_user(account_id_or_name, set_role=None, create=False):
33
35
  if set_role is not None:
34
36
  update_role(cursor, account, set_role)
35
37
 
38
+ if delete_data:
39
+ delete_user_data(conn, account)
40
+
36
41
 
37
42
  def get_account(cursor, account_id_or_name, create):
38
43
  account_id = None
geovisio/config_app.py CHANGED
@@ -9,7 +9,7 @@ from pydantic import BaseModel, EmailStr
9
9
  from pydantic.color import Color
10
10
  from pydantic.networks import HttpUrl
11
11
  import json
12
- from flask import Flask, current_app
12
+ from flask import Flask
13
13
 
14
14
  from geovisio.utils import website
15
15
  from geovisio.utils.model_query import get_db_params_and_values
@@ -17,10 +17,10 @@ from geovisio.utils.website import Website
17
17
 
18
18
 
19
19
  class ApiSummary(BaseModel):
20
- name: Dict[str, str] = {"en": "GeoVisio"}
20
+ name: Dict[str, str] = {"en": "Panoramax"}
21
21
  description: Dict[str, str] = {"en": "The open source photo mapping solution"}
22
- logo: HttpUrl = "https://gitlab.com/panoramax/gitlab-profile/-/raw/main/images/logo.svg"
23
- color: Color = "#bf360c"
22
+ logo: HttpUrl = "https://gitlab.com/panoramax/gitlab-profile/-/raw/main/images/panoramax.svg"
23
+ color: Color = "#5e499c"
24
24
  email: EmailStr = "panoramax@panoramax.fr"
25
25
  geo_coverage: Dict[str, str] = {"en": "Worldwide\nThe picture can be sent from anywhere in the world."}
26
26
 
@@ -29,7 +29,7 @@ class DefaultConfig:
29
29
  API_SUMMARY = ApiSummary()
30
30
  API_VIEWER_PAGE = "viewer.html"
31
31
  API_MAIN_PAGE = "main.html"
32
- # we default we keep the session cookie 7 days, users would have to renew their loggin after this
32
+ # we default we keep the session cookie 7 days, users would have to renew their login after this
33
33
  PERMANENT_SESSION_LIFETIME = datetime.timedelta(days=7).total_seconds()
34
34
  API_FORCE_AUTH_ON_UPLOAD = False
35
35
  PICTURE_PROCESS_DERIVATES_STRATEGY = "ON_DEMAND"
@@ -53,7 +53,8 @@ class DefaultConfig:
53
53
  API_WEBSITE_URL = (
54
54
  website.WEBSITE_UNDER_SAME_HOST
55
55
  ) # by default we consider that there is a panoramax website on the same host as the API
56
- API_REGISTRATION_IS_OPEN = False # tells that anyone can create an account. Only used for reference in the federation for the moment
56
+ API_REGISTRATION_IS_OPEN = False # tells that anyone can create an account. Used for reference in the federation and to know if we can have a `logged-only` visibility.
57
+ API_DEFAULT_PICTURE_VISIBILITY = "anyone"
57
58
 
58
59
 
59
60
  def read_config(app, test_config):
@@ -96,6 +97,7 @@ def read_config(app, test_config):
96
97
  "API_ENFORCE_TOS_ACCEPTANCE",
97
98
  "API_WEBSITE_URL",
98
99
  "API_REGISTRATION_IS_OPEN",
100
+ "API_DEFAULT_PICTURE_VISIBILITY",
99
101
  # Picture process
100
102
  "PICTURE_PROCESS_DERIVATES_STRATEGY",
101
103
  "PICTURE_PROCESS_THREADS_LIMIT",
@@ -145,7 +147,7 @@ def read_config(app, test_config):
145
147
  app.config.update(test_config)
146
148
 
147
149
  if "API_LOG_LEVEL" in app.config:
148
- logging.getLogger("geovisio").setLevel(app.config["API_LOG_LEVEL"].upper())
150
+ logging.getLogger().setLevel(app.config["API_LOG_LEVEL"].upper())
149
151
 
150
152
  # Create DB_URL from separated parameters
151
153
  if "DB_PORT" in app.config or "DB_HOST" in app.config or "DB_USERNAME" in app.config or "DB_PASSWORD" in app.config:
@@ -229,6 +231,10 @@ def read_config(app, test_config):
229
231
  if not croniter.croniter.is_valid(cron_val):
230
232
  raise Exception(f"PICTURE_PROCESS_REFRESH_CRON should be a valid cron syntax, got '{cron_val}'")
231
233
 
234
+ default_visibility = app.config["API_DEFAULT_PICTURE_VISIBILITY"]
235
+ if default_visibility not in ["anyone", "owner-only", "logged-only"]:
236
+ raise Exception(f"API_DEFAULT_PICTURE_VISIBILITY should be 'anyone', 'owner-only' or 'logged-only', got '{default_visibility}'")
237
+
232
238
  app.config["PICTURE_PROCESS_KEEP_UNBLURRED_PARTS"] = _read_bool(app.config, "PICTURE_PROCESS_KEEP_UNBLURRED_PARTS")
233
239
 
234
240
  app.config["API_ACCEPT_DUPLICATE"] = _read_bool(app.config, "API_ACCEPT_DUPLICATE")
@@ -302,6 +308,7 @@ class DBConfiguration(BaseModel):
302
308
  Not all configurations are meant to be persisted in the database"""
303
309
 
304
310
  collaborative_metadata: Optional[bool] = None
311
+ default_visibility: Optional[str] = None
305
312
 
306
313
 
307
314
  def persist_config(app: Flask):
@@ -312,13 +319,13 @@ def persist_config(app: Flask):
312
319
  """
313
320
  from geovisio.utils import db
314
321
  from psycopg.rows import class_row
315
- from psycopg.sql import SQL, Literal
316
- from psycopg.errors import UndefinedTable
322
+ from psycopg.sql import SQL
323
+ from psycopg.errors import UndefinedTable, UndefinedColumn
317
324
 
318
- with db.conn(app) as conn, conn.transaction() as tr, conn.cursor(row_factory=class_row(DBConfiguration)) as cur:
325
+ with db.conn(app) as conn, conn.transaction(), conn.cursor(row_factory=class_row(DBConfiguration)) as cur:
319
326
  try:
320
- db_config = cur.execute("SELECT * FROM configurations LIMIT 1").fetchone()
321
- except UndefinedTable:
327
+ db_config = cur.execute("SELECT collaborative_metadata, default_visibility FROM configurations LIMIT 1").fetchone()
328
+ except (UndefinedTable, UndefinedColumn):
322
329
  logging.warning("Database schema has not been updated yet, configuration will not be persisted")
323
330
  return
324
331
  if not db_config:
@@ -333,6 +340,13 @@ def persist_config(app: Flask):
333
340
  logging.warning(
334
341
  "The environment variable `API_DEFAULT_COLLABORATIVE_METADATA_EDITING` has a different value than its value in the database, it will be ignored. Update the `collaborative_metadata` field in the database if you want to change it."
335
342
  )
343
+ default_visibility = app.config["API_DEFAULT_PICTURE_VISIBILITY"]
344
+ if db_config.default_visibility is None:
345
+ config_to_persist.default_visibility = default_visibility
346
+ elif db_config.default_visibility != default_visibility and default_visibility is not None:
347
+ logging.warning(
348
+ "The environment variable `API_DEFAULT_PICTURE_VISIBILITY` has a different value than its value in the database, it will be ignored. Update the `default_visibility` field in the database if you want to change it."
349
+ )
336
350
 
337
351
  params_as_dict = get_db_params_and_values(config_to_persist)
338
352
  fields = params_as_dict.fields_for_set()