From 6d3ab76fddca88421cd46fcdec43258d2ab08a5d Mon Sep 17 00:00:00 2001 From: Ivan Ivanov Date: Mon, 9 May 2022 13:23:53 +0200 Subject: [PATCH] Merge pull request #325 from opengisch/postrelease_fixes --- .../core/migrations/0052_secret.py | 4 +- .../migrations/0054_auto_20220505_1948.py | 38 ++ docker-app/qfieldcloud/core/models.py | 13 +- .../qfieldcloud/core/permissions_utils.py | 2 - .../qfieldcloud/core/tests/test_packages.py | 20 +- .../testdata/delta/project_pgservice.qgs | 357 +++++++++++++++++- docker-app/worker_wrapper/wrapper.py | 2 +- 7 files changed, 422 insertions(+), 14 deletions(-) create mode 100644 docker-app/qfieldcloud/core/migrations/0054_auto_20220505_1948.py diff --git a/docker-app/qfieldcloud/core/migrations/0052_secret.py b/docker-app/qfieldcloud/core/migrations/0052_secret.py index cbd6780f3..2c072d09f 100644 --- a/docker-app/qfieldcloud/core/migrations/0052_secret.py +++ b/docker-app/qfieldcloud/core/migrations/0052_secret.py @@ -28,13 +28,13 @@ class Migration(migrations.Migration): ( "name", models.TextField( - help_text="Must start with a letter and followed by capital letters, numbers or underscores.", + help_text="Must start with a capital letter and followed by capital letters, numbers or underscores.", max_length=255, unique=True, validators=[ django.core.validators.RegexValidator( "^[A-Z]+[A-Z0-9_]+$", - "Must start with a letter and followed by capital letters, numbers or underscores.", + "Must start with a capital letter and followed by capital letters, numbers or underscores.", ) ], ), diff --git a/docker-app/qfieldcloud/core/migrations/0054_auto_20220505_1948.py b/docker-app/qfieldcloud/core/migrations/0054_auto_20220505_1948.py new file mode 100644 index 000000000..c40a58e02 --- /dev/null +++ b/docker-app/qfieldcloud/core/migrations/0054_auto_20220505_1948.py @@ -0,0 +1,38 @@ +# Generated by Django 3.2.13 on 2022-05-05 17:48 + +import django.core.validators +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("core", "0053_project_last_package"), + ] + + operations = [ + migrations.AlterModelOptions( + name="secret", + options={"ordering": ["project", "name"]}, + ), + migrations.AlterField( + model_name="secret", + name="name", + field=models.TextField( + help_text="Must start with a capital letter and followed by capital letters, numbers or underscores.", + max_length=255, + validators=[ + django.core.validators.RegexValidator( + "^[A-Z]+[A-Z0-9_]+$", + "Must start with a capital letter and followed by capital letters, numbers or underscores.", + ) + ], + ), + ), + migrations.AddConstraint( + model_name="secret", + constraint=models.UniqueConstraint( + fields=("project", "name"), name="secret_project_name_uniq" + ), + ), + ] diff --git a/docker-app/qfieldcloud/core/models.py b/docker-app/qfieldcloud/core/models.py index ee94f7a52..713bd4b72 100644 --- a/docker-app/qfieldcloud/core/models.py +++ b/docker-app/qfieldcloud/core/models.py @@ -1283,18 +1283,17 @@ class Type(models.TextChoices): name = models.TextField( max_length=255, - unique=True, validators=[ RegexValidator( r"^[A-Z]+[A-Z0-9_]+$", _( - "Must start with a letter and followed by capital letters, numbers or underscores." + "Must start with a capital letter and followed by capital letters, numbers or underscores." ), ) ], help_text=_( _( - "Must start with a letter and followed by capital letters, numbers or underscores." + "Must start with a capital letter and followed by capital letters, numbers or underscores." ), ), ) @@ -1308,6 +1307,14 @@ class Type(models.TextChoices): created_at = models.DateTimeField(auto_now_add=True) value = django_cryptography.fields.encrypt(models.TextField()) + class Meta: + ordering = ["project", "name"] + constraints = [ + models.UniqueConstraint( + fields=["project", "name"], name="secret_project_name_uniq" + ) + ] + auditlog.register(User, exclude_fields=["last_login", "updated_at"]) auditlog.register(UserAccount) diff --git a/docker-app/qfieldcloud/core/permissions_utils.py b/docker-app/qfieldcloud/core/permissions_utils.py index ffa14f0be..8b568d1f7 100644 --- a/docker-app/qfieldcloud/core/permissions_utils.py +++ b/docker-app/qfieldcloud/core/permissions_utils.py @@ -336,7 +336,6 @@ def can_create_secrets(user: QfcUser, project: Project) -> bool: project, [ ProjectCollaborator.Roles.ADMIN, - ProjectCollaborator.Roles.MANAGER, ], ) @@ -347,7 +346,6 @@ def can_delete_secrets(user: QfcUser, project: Project) -> bool: project, [ ProjectCollaborator.Roles.ADMIN, - ProjectCollaborator.Roles.MANAGER, ], ) diff --git a/docker-app/qfieldcloud/core/tests/test_packages.py b/docker-app/qfieldcloud/core/tests/test_packages.py index 148ec2b5d..3f32688ac 100644 --- a/docker-app/qfieldcloud/core/tests/test_packages.py +++ b/docker-app/qfieldcloud/core/tests/test_packages.py @@ -446,12 +446,28 @@ def test_connects_via_pgservice(self): self.conn.commit() Secret.objects.create( - name="PG_SERVICE_GEODB", + name="PG_SERVICE_GEODB1", type=Secret.Type.PGSERVICE, project=self.project1, created_by=self.project1.owner, value=( - "[geodb]\n" + "[geodb1]\n" + "dbname=test\n" + "host=geodb\n" + "port=5432\n" + f"user={os.environ.get('GEODB_USER')}\n" + f"password={os.environ.get('GEODB_PASSWORD')}\n" + "sslmode=disable\n" + ), + ) + + Secret.objects.create( + name="PG_SERVICE_GEODB2", + type=Secret.Type.PGSERVICE, + project=self.project1, + created_by=self.project1.owner, + value=( + "[geodb2]\n" "dbname=test\n" "host=geodb\n" "port=5432\n" diff --git a/docker-app/qfieldcloud/core/tests/testdata/delta/project_pgservice.qgs b/docker-app/qfieldcloud/core/tests/testdata/delta/project_pgservice.qgs index 80c922669..790222238 100644 --- a/docker-app/qfieldcloud/core/tests/testdata/delta/project_pgservice.qgs +++ b/docker-app/qfieldcloud/core/tests/testdata/delta/project_pgservice.qgs @@ -1,4 +1,4 @@ - + @@ -21,13 +21,19 @@ - + + + + + + point_6b900fa7_af52_4082_bbff_6077f4a91d02 + point_6b900fa7_af52_4082_bbff_6077f4a91d03 @@ -159,6 +165,11 @@ + + + @@ -226,7 +237,344 @@ 46.81186962046260902 point_6b900fa7_af52_4082_bbff_6077f4a91d02 - service='geodb' sslmode=disable key='id' srid=2056 type=Point checkPrimaryKeyUnicity='0' table="public"."point" (geometry) + service='geodb1' sslmode=disable key='id' srid=2056 type=Point checkPrimaryKeyUnicity='0' table="public"."point" (geometry) + + + + point + + + GEOGCRS["WGS 84",DATUM["World Geodetic System 1984",ELLIPSOID["WGS 84",6378137,298.257223563,LENGTHUNIT["metre",1]]],PRIMEM["Greenwich",0,ANGLEUNIT["degree",0.0174532925199433]],CS[ellipsoidal,2],AXIS["geodetic latitude (Lat)",north,ORDER[1],ANGLEUNIT["degree",0.0174532925199433]],AXIS["geodetic longitude (Lon)",east,ORDER[2],ANGLEUNIT["degree",0.0174532925199433]],USAGE[SCOPE["unknown"],AREA["World"],BBOX[-90,-180,90,180]],ID["EPSG",4326]] + +proj=longlat +datum=WGS84 +no_defs + 3452 + 4326 + EPSG:4326 + WGS 84 + longlat + EPSG:7030 + true + + + + + + + dataset + + + + + + + + GEOGCRS["WGS 84",DATUM["World Geodetic System 1984",ELLIPSOID["WGS 84",6378137,298.257223563,LENGTHUNIT["metre",1]]],PRIMEM["Greenwich",0,ANGLEUNIT["degree",0.0174532925199433]],CS[ellipsoidal,2],AXIS["geodetic latitude (Lat)",north,ORDER[1],ANGLEUNIT["degree",0.0174532925199433]],AXIS["geodetic longitude (Lon)",east,ORDER[2],ANGLEUNIT["degree",0.0174532925199433]],USAGE[SCOPE["unknown"],AREA["World"],BBOX[-90,-180,90,180]],ID["EPSG",4326]] + +proj=longlat +datum=WGS84 +no_defs + 3452 + 4326 + EPSG:4326 + WGS 84 + longlat + EPSG:7030 + true + + + + + postgres + + + + + + + + + + + 1 + 1 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + 0 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + 0 + generatedlayout + + + + + + + + + + + 9.25874912335106437 + 46.81162678053534165 + 9.25922364550132926 + 46.81186962046260902 + + + 9.25874912335106437 + 46.81162678053534165 + 9.25922364550132926 + 46.81186962046260902 + + point_6b900fa7_af52_4082_bbff_6077f4a91d03 + service='geodb2' sslmode=disable key='id' srid=2056 type=Point checkPrimaryKeyUnicity='0' table="public"."point" (geometry) @@ -552,6 +900,7 @@ + @@ -709,7 +1058,7 @@ - + PROJCRS["CH1903+ / LV95",BASEGEOGCRS["CH1903+",DATUM["CH1903+",ELLIPSOID["Bessel 1841",6377397.155,299.1528128,LENGTHUNIT["metre",1]]],PRIMEM["Greenwich",0,ANGLEUNIT["degree",0.0174532925199433]],ID["EPSG",4150]],CONVERSION["Swiss Oblique Mercator 1995",METHOD["Hotine Oblique Mercator (variant B)",ID["EPSG",9815]],PARAMETER["Latitude of projection centre",46.9524055555556,ANGLEUNIT["degree",0.0174532925199433],ID["EPSG",8811]],PARAMETER["Longitude of projection centre",7.43958333333333,ANGLEUNIT["degree",0.0174532925199433],ID["EPSG",8812]],PARAMETER["Azimuth of initial line",90,ANGLEUNIT["degree",0.0174532925199433],ID["EPSG",8813]],PARAMETER["Angle from Rectified to Skew Grid",90,ANGLEUNIT["degree",0.0174532925199433],ID["EPSG",8814]],PARAMETER["Scale factor on initial line",1,SCALEUNIT["unity",1],ID["EPSG",8815]],PARAMETER["Easting at projection centre",2600000,LENGTHUNIT["metre",1],ID["EPSG",8816]],PARAMETER["Northing at projection centre",1200000,LENGTHUNIT["metre",1],ID["EPSG",8817]]],CS[Cartesian,2],AXIS["(E)",east,ORDER[1],LENGTHUNIT["metre",1]],AXIS["(N)",north,ORDER[2],LENGTHUNIT["metre",1]],USAGE[SCOPE["unknown"],AREA["Europe - Liechtenstein and Switzerland"],BBOX[45.82,5.96,47.81,10.49]],ID["EPSG",2056]] +proj=somerc +lat_0=46.9524055555556 +lon_0=7.43958333333333 +k_0=1 +x_0=2600000 +y_0=1200000 +ellps=bessel +towgs84=674.374,15.056,405.346,0,0,0,0 +units=m +no_defs diff --git a/docker-app/worker_wrapper/wrapper.py b/docker-app/worker_wrapper/wrapper.py index 5a0a4cd00..6c864f79d 100644 --- a/docker-app/worker_wrapper/wrapper.py +++ b/docker-app/worker_wrapper/wrapper.py @@ -210,7 +210,7 @@ def _run_docker( if secret.type == Secret.Type.ENVVAR: extra_envvars[secret.name] = secret.value elif secret.type == Secret.Type.PGSERVICE: - pgservice_file_contents += f"\r\n{secret.value}" + pgservice_file_contents += f"\n{secret.value}" else: raise NotImplementedError(f"Unknown secret type: {secret.type}")