Merge pull request 'master' (#484) from master into Docker
Reviewed-on: #484
This commit is contained in:
commit
0b8176db2e
@ -86,7 +86,7 @@ class EcoAccountWorkflowTestCase(BaseWorkflowTestCase):
|
||||
new_title = self.create_dummy_string()
|
||||
new_identifier = self.create_dummy_string()
|
||||
new_comment = self.create_dummy_string()
|
||||
new_geometry = MultiPolygon(srid=4326) # Create an empty geometry
|
||||
new_geometry = self.create_dummy_geometry()
|
||||
test_conservation_office = self.get_conservation_office_code()
|
||||
test_deductable_surface = self.eco_account.deductable_surface + 100
|
||||
|
||||
@ -103,7 +103,7 @@ class EcoAccountWorkflowTestCase(BaseWorkflowTestCase):
|
||||
"identifier": new_identifier,
|
||||
"title": new_title,
|
||||
"comment": new_comment,
|
||||
"geom": new_geometry.geojson,
|
||||
"geom": self.create_geojson(new_geometry),
|
||||
"surface": test_deductable_surface,
|
||||
"conservation_office": test_conservation_office.id
|
||||
}
|
||||
|
||||
@ -84,7 +84,7 @@ class EmaWorkflowTestCase(BaseWorkflowTestCase):
|
||||
new_title = self.create_dummy_string()
|
||||
new_identifier = self.create_dummy_string()
|
||||
new_comment = self.create_dummy_string()
|
||||
new_geometry = MultiPolygon(srid=4326) # Create an empty geometry
|
||||
new_geometry = self.create_dummy_geometry() # Create an empty geometry
|
||||
test_conservation_office = self.get_conservation_office_code()
|
||||
|
||||
check_on_elements = {
|
||||
@ -99,7 +99,7 @@ class EmaWorkflowTestCase(BaseWorkflowTestCase):
|
||||
"identifier": new_identifier,
|
||||
"title": new_title,
|
||||
"comment": new_comment,
|
||||
"geom": new_geometry.geojson,
|
||||
"geom": self.create_geojson(new_geometry),
|
||||
"conservation_office": test_conservation_office.id
|
||||
}
|
||||
self.client_user.post(url, post_data)
|
||||
|
||||
@ -124,7 +124,7 @@ class EditInterventionFormTestCase(NewInterventionFormTestCase):
|
||||
self.assertIsNotNone(obj.responsible.handler)
|
||||
self.assertEqual(obj.title, data["title"])
|
||||
self.assertEqual(obj.comment, data["comment"])
|
||||
self.assertTrue(test_geom.equals_exact(obj.geometry.geom, 0.000001))
|
||||
self.assert_equal_geometries(test_geom, obj.geometry.geom)
|
||||
|
||||
self.assertEqual(obj.legal.binding_date, today)
|
||||
self.assertEqual(obj.legal.registration_date, today)
|
||||
|
||||
@ -72,9 +72,8 @@ class SimpleGeomForm(BaseForm):
|
||||
# will be rendered again on failed submit
|
||||
self.initialize_form_field("geom", self.data["geom"])
|
||||
|
||||
# Read geojson into gdal geometry
|
||||
# HINT: This can be simplified if the geojson format holds data in epsg:4326 (GDAL provides direct creation for
|
||||
# this case)
|
||||
# Initialize features list with empty MultiPolygon, so that an empty input will result in a
|
||||
# proper empty MultiPolygon object
|
||||
features = []
|
||||
features_json = geom.get("features", [])
|
||||
accepted_ogr_types = [
|
||||
@ -102,19 +101,22 @@ class SimpleGeomForm(BaseForm):
|
||||
return is_valid
|
||||
|
||||
is_valid &= self.__is_area_valid(g)
|
||||
|
||||
polygon = Polygon.from_ewkt(g.ewkt)
|
||||
is_valid &= polygon.valid
|
||||
if not polygon.valid:
|
||||
self.add_error("geom", polygon.valid_reason)
|
||||
g = Polygon.from_ewkt(g.ewkt)
|
||||
is_valid &= g.valid
|
||||
if not g.valid:
|
||||
self.add_error("geom", g.valid_reason)
|
||||
return is_valid
|
||||
|
||||
features.append(polygon)
|
||||
if isinstance(g, Polygon):
|
||||
features.append(g)
|
||||
elif isinstance(g, MultiPolygon):
|
||||
features.extend(list(g))
|
||||
|
||||
# Unionize all geometry features into one new MultiPolygon
|
||||
form_geom = MultiPolygon(srid=DEFAULT_SRID_RLP)
|
||||
for feature in features:
|
||||
form_geom = form_geom.union(feature)
|
||||
if features:
|
||||
form_geom = MultiPolygon(*features, srid=DEFAULT_SRID_RLP).unary_union
|
||||
else:
|
||||
form_geom = MultiPolygon(srid=DEFAULT_SRID_RLP)
|
||||
|
||||
# Make sure to convert into a MultiPolygon. Relevant if a single Polygon is provided.
|
||||
form_geom = Geometry.cast_to_multipolygon(form_geom)
|
||||
|
||||
@ -395,7 +395,7 @@ class Geometry(BaseResource):
|
||||
output_geom
|
||||
"""
|
||||
output_geom = input_geom
|
||||
if input_geom.geom_type != "MultiPolygon":
|
||||
if not isinstance(input_geom, MultiPolygon):
|
||||
output_geom = MultiPolygon(input_geom, srid=DEFAULT_SRID_RLP)
|
||||
return output_geom
|
||||
|
||||
|
||||
@ -469,7 +469,7 @@ class BaseTestCase(TestCase):
|
||||
eco_account.save()
|
||||
return eco_account
|
||||
|
||||
def assert_equal_geometries(self, geom1: MultiPolygon, geom2: MultiPolygon, tolerance = 0.001):
|
||||
def assert_equal_geometries(self, geom1: MultiPolygon, geom2: MultiPolygon, tolerance=0.001):
|
||||
""" Assert for geometries to be equal
|
||||
|
||||
Transforms the geometries to matching srids before checking
|
||||
@ -491,7 +491,10 @@ class BaseTestCase(TestCase):
|
||||
# transformation from one coordinate system into the other, which is valid
|
||||
geom1.transform(geom2.srid)
|
||||
geom2.transform(geom1.srid)
|
||||
self.assertTrue(geom1.equals_exact(geom2, tolerance) or geom2.equals_exact(geom1, tolerance))
|
||||
self.assertTrue(
|
||||
geom1.equals_exact(geom2, tolerance=tolerance),
|
||||
msg=f"Difference is {abs(geom1.area - geom2.area)} with {geom1.area} and {geom2.area} in a tolerance of {tolerance}"
|
||||
)
|
||||
|
||||
|
||||
class BaseViewTestCase(BaseTestCase):
|
||||
|
||||
@ -15,6 +15,7 @@ class UserNotificationAdmin(admin.ModelAdmin):
|
||||
class UserAdmin(admin.ModelAdmin):
|
||||
list_display = [
|
||||
"id",
|
||||
"sso_identifier",
|
||||
"username",
|
||||
"first_name",
|
||||
"last_name",
|
||||
|
||||
18
user/migrations/0010_user_sso_identifier.py
Normal file
18
user/migrations/0010_user_sso_identifier.py
Normal file
@ -0,0 +1,18 @@
|
||||
# Generated by Django 5.1.6 on 2025-09-12 06:10
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('user', '0009_user_oauth_token'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='user',
|
||||
name='sso_identifier',
|
||||
field=models.CharField(blank=True, db_comment='Identifies the account based on an unique identifier from the SSO system', max_length=255, null=True),
|
||||
),
|
||||
]
|
||||
@ -6,6 +6,7 @@ Created on: 15.11.21
|
||||
|
||||
"""
|
||||
from django.contrib.auth.models import AbstractUser
|
||||
from django.core.exceptions import ObjectDoesNotExist
|
||||
|
||||
from django.db import models
|
||||
|
||||
@ -32,6 +33,12 @@ class User(AbstractUser):
|
||||
db_comment="OAuth token for the user",
|
||||
related_name="+"
|
||||
)
|
||||
sso_identifier = models.CharField(
|
||||
blank=True,
|
||||
null=True,
|
||||
db_comment="Identifies the account based on an unique identifier from the SSO system",
|
||||
max_length=255,
|
||||
)
|
||||
|
||||
def is_notification_setting_set(self, notification_enum: UserNotificationEnum):
|
||||
return self.notifications.filter(
|
||||
@ -264,4 +271,48 @@ class User(AbstractUser):
|
||||
self.oauth_token.delete()
|
||||
self.oauth_token = token
|
||||
self.save()
|
||||
return self
|
||||
return self
|
||||
|
||||
@staticmethod
|
||||
def resolve_user_using_propagation_data(data: dict):
|
||||
""" Fetches user from db by the given data from propagation process
|
||||
|
||||
Args:
|
||||
data (dict): json containing user information from the sso system
|
||||
|
||||
Returns:
|
||||
user (User): The resolved user
|
||||
"""
|
||||
username = data.get("username", None)
|
||||
sso_identifier = data.get("sso_identifier", None)
|
||||
if not username and not sso_identifier:
|
||||
raise AssertionError("No username or sso identifier provided")
|
||||
|
||||
try:
|
||||
user = User.objects.get(username=username)
|
||||
except ObjectDoesNotExist:
|
||||
try:
|
||||
user = User.objects.get(sso_identifier=sso_identifier)
|
||||
except ObjectDoesNotExist:
|
||||
raise ObjectDoesNotExist("No user with this username or sso identifier was found")
|
||||
|
||||
return user
|
||||
|
||||
def update_user_using_propagation_data(self, data: dict):
|
||||
""" Update user data based on propagation data from sso system
|
||||
|
||||
Args:
|
||||
data (dict): json containing user information from the sso system
|
||||
|
||||
Returns:
|
||||
user (User): The updated user
|
||||
"""
|
||||
skipable_attrs = {
|
||||
"is_staff",
|
||||
"is_superuser",
|
||||
}
|
||||
for _attr, _val in data.items():
|
||||
if _attr in skipable_attrs:
|
||||
continue
|
||||
setattr(self, _attr, _val)
|
||||
return self
|
||||
|
||||
@ -44,17 +44,8 @@ class PropagateUserView(View):
|
||||
|
||||
try:
|
||||
status = "updated"
|
||||
user = User.objects.get(username=body.get('username'))
|
||||
# Update user data, excluding some changes
|
||||
skipable_attrs = {
|
||||
"username",
|
||||
"is_staff",
|
||||
"is_superuser",
|
||||
}
|
||||
for _attr, _val in body.items():
|
||||
if _attr in skipable_attrs:
|
||||
continue
|
||||
setattr(user, _attr, _val)
|
||||
user = User.resolve_user_using_propagation_data(body)
|
||||
user = user.update_user_using_propagation_data(body)
|
||||
except ObjectDoesNotExist:
|
||||
user = User(**body)
|
||||
status = "created"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user