Compare commits
39 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d4d39689cc | |||
| 2fde3f0fa3 | |||
| b62c2e92c9 | |||
| 1c0fb801e6 | |||
| a1acff5e90 | |||
| 25a92f59aa | |||
| 884db6f014 | |||
| 59b7f3c69a | |||
| 0446d50438 | |||
| 12f78c85bf | |||
| 78485a4506 | |||
| 21a5c84b18 | |||
| a93f509d51 | |||
| 38967da201 | |||
| 60d749db2d | |||
| dff577309e | |||
| ea590d0868 | |||
| e09c15bd51 | |||
| c3019f83fd | |||
| 93a71a7055 | |||
| 35b1409359 | |||
| c9aeb393b5 | |||
| 6df46e7642 | |||
| fe366bc568 | |||
| a9f04a28c1 | |||
| 8c9f4888dd | |||
| 5c727b2eaa | |||
| 76b2a78fe2 | |||
| 86db08fca0 | |||
| fe1dce6440 | |||
| a5e6f5a1db | |||
| 78e9cbab71 | |||
| 572348f9f1 | |||
| 8ff3cb9adc | |||
| f135008447 | |||
| 94b7f3ad70 | |||
| d69bab36da | |||
| b441518334 | |||
| 1a80912960 |
46
.env.sample
Normal file
46
.env.sample
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
# General
|
||||||
|
SECRET_KEY=CHANGE_ME
|
||||||
|
DEBUG=True
|
||||||
|
ALLOWED_HOSTS=127.0.0.1,localhost,example.org
|
||||||
|
BASE_URL=http://localhost:8002
|
||||||
|
ADMINS=Admin1:mail@example.org,Admin2:mail2@example.org
|
||||||
|
|
||||||
|
# Database
|
||||||
|
DB_USER=postgres
|
||||||
|
DB_PASSWORD=
|
||||||
|
DB_NAME=konova
|
||||||
|
DB_HOST=127.0.0.1
|
||||||
|
DB_PORT=5432
|
||||||
|
|
||||||
|
# Redis (for celery)
|
||||||
|
REDIS_HOST=CHANGE_ME
|
||||||
|
REDIS_PORT=CHANGE_ME
|
||||||
|
|
||||||
|
# E-Mail
|
||||||
|
SMTP_HOST=localhost
|
||||||
|
SMTP_PORT=25
|
||||||
|
REPLY_TO_ADDR=ksp-servicestelle@sgdnord.rlp.de
|
||||||
|
DEFAULT_FROM_EMAIL=service@ksp.de
|
||||||
|
|
||||||
|
# Proxy
|
||||||
|
PROXY=CHANGE_ME
|
||||||
|
GEOPORTAL_RLP_USER=CHANGE_ME
|
||||||
|
GEOPORTAL_RLP_PASSWORD=CHANGE_ME
|
||||||
|
|
||||||
|
# Schneider
|
||||||
|
SCHNEIDER_BASE_URL=https://schneider.naturschutz.rlp.de
|
||||||
|
SCHNEIDER_AUTH_TOKEN=CHANGE_ME
|
||||||
|
SCHNEIDER_AUTH_HEADER=auth
|
||||||
|
|
||||||
|
# SSO
|
||||||
|
SSO_SERVER_BASE_URL=https://login.naturschutz.rlp.de
|
||||||
|
OAUTH_CODE_VERIFIER=CHANGE_ME
|
||||||
|
OAUTH_CLIENT_ID=CHANGE_ME
|
||||||
|
OAUTH_CLIENT_SECRET=CHANGE_ME
|
||||||
|
|
||||||
|
# RabbitMQ
|
||||||
|
## For connections to EGON
|
||||||
|
EGON_RABBITMQ_HOST=CHANGE_ME
|
||||||
|
EGON_RABBITMQ_PORT=CHANGE_ME
|
||||||
|
EGON_RABBITMQ_USER=CHANGE_ME
|
||||||
|
EGON_RABBITMQ_PW=CHANGE_ME
|
||||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -3,3 +3,4 @@
|
|||||||
/.idea/
|
/.idea/
|
||||||
/.coverage
|
/.coverage
|
||||||
/htmlcov/
|
/htmlcov/
|
||||||
|
/.env
|
||||||
|
|||||||
15
api/admin.py
15
api/admin.py
@@ -1,6 +1,6 @@
|
|||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
|
|
||||||
from api.models.token import APIUserToken
|
from api.models.token import APIUserToken, OAuthToken
|
||||||
|
|
||||||
|
|
||||||
class APITokenAdmin(admin.ModelAdmin):
|
class APITokenAdmin(admin.ModelAdmin):
|
||||||
@@ -17,4 +17,17 @@ class APITokenAdmin(admin.ModelAdmin):
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
class OAuthTokenAdmin(admin.ModelAdmin):
|
||||||
|
list_display = [
|
||||||
|
"access_token",
|
||||||
|
"refresh_token",
|
||||||
|
"expires_on",
|
||||||
|
]
|
||||||
|
search_fields = [
|
||||||
|
"access_token",
|
||||||
|
"refresh_token",
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
admin.site.register(APIUserToken, APITokenAdmin)
|
admin.site.register(APIUserToken, APITokenAdmin)
|
||||||
|
admin.site.register(OAuthToken, OAuthTokenAdmin)
|
||||||
|
|||||||
26
api/migrations/0003_oauthtoken.py
Normal file
26
api/migrations/0003_oauthtoken.py
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
# Generated by Django 5.0.4 on 2024-04-30 07:20
|
||||||
|
|
||||||
|
import uuid
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('api', '0002_alter_apiusertoken_valid_until'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='OAuthToken',
|
||||||
|
fields=[
|
||||||
|
('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
|
||||||
|
('access_token', models.CharField(db_comment='OAuth access token', max_length=255)),
|
||||||
|
('refresh_token', models.CharField(db_comment='OAuth refresh token', max_length=255)),
|
||||||
|
('expires_on', models.DateTimeField(db_comment='When the token will be expired')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'abstract': False,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -1,7 +1,14 @@
|
|||||||
|
import json
|
||||||
|
from datetime import timedelta
|
||||||
|
|
||||||
|
import requests
|
||||||
from django.core.exceptions import ObjectDoesNotExist
|
from django.core.exceptions import ObjectDoesNotExist
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
|
from django.utils.timezone import now
|
||||||
|
|
||||||
|
from konova.models import UuidModel
|
||||||
|
from konova.sub_settings.sso_settings import OAUTH_CLIENT_ID, OAUTH_CLIENT_SECRET, SSO_SERVER_BASE
|
||||||
from konova.utils.generators import generate_token
|
from konova.utils.generators import generate_token
|
||||||
|
|
||||||
|
|
||||||
@@ -46,3 +53,105 @@ class APIUserToken(models.Model):
|
|||||||
except ObjectDoesNotExist:
|
except ObjectDoesNotExist:
|
||||||
raise PermissionError("Credentials invalid")
|
raise PermissionError("Credentials invalid")
|
||||||
return token_obj.user
|
return token_obj.user
|
||||||
|
|
||||||
|
|
||||||
|
class OAuthToken(UuidModel):
|
||||||
|
access_token = models.CharField(
|
||||||
|
max_length=255,
|
||||||
|
blank=False,
|
||||||
|
null=False,
|
||||||
|
db_comment="OAuth access token"
|
||||||
|
)
|
||||||
|
refresh_token = models.CharField(
|
||||||
|
max_length=255,
|
||||||
|
blank=False,
|
||||||
|
null=False,
|
||||||
|
db_comment="OAuth refresh token"
|
||||||
|
)
|
||||||
|
expires_on = models.DateTimeField(
|
||||||
|
db_comment="When the token will be expired"
|
||||||
|
)
|
||||||
|
|
||||||
|
ASSUMED_LATENCY = 1000 # assumed latency between creation and receiving of an access token
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return str(self.access_token)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def from_access_token_response(access_token_data: str, received_on):
|
||||||
|
"""
|
||||||
|
Creates an OAuthToken based on retrieved access token data (OAuth2.0 specification)
|
||||||
|
|
||||||
|
Args:
|
||||||
|
access_token_data (str): OAuth2.0 response data
|
||||||
|
received_on (): Timestamp when the response has been received
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
"""
|
||||||
|
oauth_token = OAuthToken()
|
||||||
|
data = json.loads(access_token_data)
|
||||||
|
|
||||||
|
oauth_token.access_token = data.get("access_token")
|
||||||
|
oauth_token.refresh_token = data.get("refresh_token")
|
||||||
|
|
||||||
|
expires_on = received_on + timedelta(
|
||||||
|
seconds=(data.get("expires_in") + OAuthToken.ASSUMED_LATENCY)
|
||||||
|
)
|
||||||
|
oauth_token.expires_on = expires_on
|
||||||
|
|
||||||
|
return oauth_token
|
||||||
|
|
||||||
|
def refresh(self):
|
||||||
|
url = f"{SSO_SERVER_BASE}o/token/"
|
||||||
|
params = {
|
||||||
|
"grant_type": "refresh_token",
|
||||||
|
"refresh_token": self.refresh_token,
|
||||||
|
"client_id": OAUTH_CLIENT_ID,
|
||||||
|
"client_secret": OAUTH_CLIENT_SECRET
|
||||||
|
}
|
||||||
|
response = requests.post(
|
||||||
|
url,
|
||||||
|
params
|
||||||
|
)
|
||||||
|
_now = now()
|
||||||
|
is_response_invalid = response.status_code != 200
|
||||||
|
if is_response_invalid:
|
||||||
|
raise RuntimeError(f"Refreshing token not possible: {response.status_code}")
|
||||||
|
|
||||||
|
response_content = response.content.decode("utf-8")
|
||||||
|
response_content = json.loads(response_content)
|
||||||
|
|
||||||
|
access_token = response_content.get("access_token")
|
||||||
|
refresh_token = response_content.get("refresh_token")
|
||||||
|
expires_in = response_content.get("expires")
|
||||||
|
|
||||||
|
self.access_token = access_token
|
||||||
|
self.refresh_token = refresh_token
|
||||||
|
self.expires_in = expires_in
|
||||||
|
self.save()
|
||||||
|
|
||||||
|
return self
|
||||||
|
|
||||||
|
def update_and_get_user(self):
|
||||||
|
from user.models import User
|
||||||
|
url = f"{SSO_SERVER_BASE}users/oauth/data/"
|
||||||
|
|
||||||
|
access_token = self.access_token
|
||||||
|
response = requests.get(
|
||||||
|
url,
|
||||||
|
headers={
|
||||||
|
"Authorization": f"Bearer {access_token}",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
is_response_code_invalid = response.status_code != 200
|
||||||
|
if is_response_code_invalid:
|
||||||
|
raise RuntimeError(f"OAuth user data fetching unsuccessful: {response.status_code}")
|
||||||
|
|
||||||
|
response_content = response.content.decode("utf-8")
|
||||||
|
response_content = json.loads(response_content)
|
||||||
|
user = User.oauth_update_user(response_content)
|
||||||
|
|
||||||
|
return user
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ from abc import abstractmethod
|
|||||||
from django.contrib.gis import geos
|
from django.contrib.gis import geos
|
||||||
from django.contrib.gis.geos import GEOSGeometry
|
from django.contrib.gis.geos import GEOSGeometry
|
||||||
from django.core.paginator import Paginator
|
from django.core.paginator import Paginator
|
||||||
|
from django.db.models import Q
|
||||||
|
|
||||||
from konova.sub_settings.lanis_settings import DEFAULT_SRID_RLP
|
from konova.sub_settings.lanis_settings import DEFAULT_SRID_RLP
|
||||||
from konova.utils.message_templates import DATA_UNSHARED
|
from konova.utils.message_templates import DATA_UNSHARED
|
||||||
@@ -32,8 +33,8 @@ class AbstractModelAPISerializer:
|
|||||||
self.lookup = {
|
self.lookup = {
|
||||||
"id": None, # must be set
|
"id": None, # must be set
|
||||||
"deleted__isnull": True,
|
"deleted__isnull": True,
|
||||||
"users__in": [], # must be set
|
|
||||||
}
|
}
|
||||||
|
self.shared_lookup = Q() # must be set, so user or team based share will be used properly
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
@@ -76,7 +77,11 @@ class AbstractModelAPISerializer:
|
|||||||
else:
|
else:
|
||||||
# Return certain object
|
# Return certain object
|
||||||
self.lookup["id"] = _id
|
self.lookup["id"] = _id
|
||||||
self.lookup["users__in"] = [user]
|
|
||||||
|
self.shared_lookup = Q(
|
||||||
|
Q(users__in=[user]) |
|
||||||
|
Q(teams__in=list(user.shared_teams))
|
||||||
|
)
|
||||||
|
|
||||||
def fetch_and_serialize(self):
|
def fetch_and_serialize(self):
|
||||||
""" Serializes the model entry according to the given lookup data
|
""" Serializes the model entry according to the given lookup data
|
||||||
@@ -86,7 +91,13 @@ class AbstractModelAPISerializer:
|
|||||||
Returns:
|
Returns:
|
||||||
serialized_data (dict)
|
serialized_data (dict)
|
||||||
"""
|
"""
|
||||||
entries = self.model.objects.filter(**self.lookup).order_by("id")
|
entries = self.model.objects.filter(
|
||||||
|
**self.lookup
|
||||||
|
).filter(
|
||||||
|
self.shared_lookup
|
||||||
|
).order_by(
|
||||||
|
"id"
|
||||||
|
).distinct()
|
||||||
self.paginator = Paginator(entries, self.rpp)
|
self.paginator = Paginator(entries, self.rpp)
|
||||||
requested_entries = self.paginator.page(self.page_number)
|
requested_entries = self.paginator.page(self.page_number)
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ Created on: 24.01.22
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
from django.db import transaction
|
from django.db import transaction
|
||||||
|
from django.db.models import Q
|
||||||
|
|
||||||
from api.utils.serializer.v1.serializer import AbstractModelAPISerializerV1, AbstractCompensationAPISerializerV1Mixin
|
from api.utils.serializer.v1.serializer import AbstractModelAPISerializerV1, AbstractCompensationAPISerializerV1Mixin
|
||||||
from compensation.models import Compensation
|
from compensation.models import Compensation
|
||||||
@@ -21,8 +22,10 @@ class CompensationAPISerializerV1(AbstractModelAPISerializerV1, AbstractCompensa
|
|||||||
|
|
||||||
def prepare_lookup(self, id, user):
|
def prepare_lookup(self, id, user):
|
||||||
super().prepare_lookup(id, user)
|
super().prepare_lookup(id, user)
|
||||||
del self.lookup["users__in"]
|
self.shared_lookup = Q(
|
||||||
self.lookup["intervention__users__in"] = [user]
|
Q(intervention__users__in=[user]) |
|
||||||
|
Q(intervention__teams__in=user.shared_teams)
|
||||||
|
)
|
||||||
|
|
||||||
def intervention_to_json(self, entry):
|
def intervention_to_json(self, entry):
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ Created on: 28.01.22
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
from django.core.exceptions import ObjectDoesNotExist
|
from django.core.exceptions import ObjectDoesNotExist
|
||||||
|
from django.db.models import Q
|
||||||
|
|
||||||
from api.utils.serializer.v1.serializer import DeductableAPISerializerV1Mixin, AbstractModelAPISerializerV1
|
from api.utils.serializer.v1.serializer import DeductableAPISerializerV1Mixin, AbstractModelAPISerializerV1
|
||||||
from compensation.models import EcoAccountDeduction, EcoAccount
|
from compensation.models import EcoAccountDeduction, EcoAccount
|
||||||
@@ -28,9 +29,11 @@ class DeductionAPISerializerV1(AbstractModelAPISerializerV1,
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
super().prepare_lookup(_id, user)
|
super().prepare_lookup(_id, user)
|
||||||
del self.lookup["users__in"]
|
|
||||||
del self.lookup["deleted__isnull"]
|
del self.lookup["deleted__isnull"]
|
||||||
self.lookup["intervention__users__in"] = [user]
|
self.shared_lookup = Q(
|
||||||
|
Q(intervention__users__in=[user]) |
|
||||||
|
Q(intervention__teams__in=user.shared_teams)
|
||||||
|
)
|
||||||
|
|
||||||
def _model_to_geo_json(self, entry):
|
def _model_to_geo_json(self, entry):
|
||||||
""" Adds the basic data
|
""" Adds the basic data
|
||||||
|
|||||||
@@ -23,11 +23,6 @@ class AbstractAPIViewV1(AbstractAPIView):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
self.lookup = {
|
|
||||||
"id": None, # must be set in subclasses
|
|
||||||
"deleted__isnull": True,
|
|
||||||
"users__in": [], # must be set in subclasses
|
|
||||||
}
|
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
self.serializer = self.serializer()
|
self.serializer = self.serializer()
|
||||||
|
|
||||||
|
|||||||
@@ -75,7 +75,8 @@ class KonovaCode(models.Model):
|
|||||||
return self
|
return self
|
||||||
|
|
||||||
children = KonovaCode.objects.filter(
|
children = KonovaCode.objects.filter(
|
||||||
parent=self
|
parent=self,
|
||||||
|
is_archived=False,
|
||||||
).order_by(
|
).order_by(
|
||||||
order_by
|
order_by
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ Contact: michel.peltriaux@sgdnord.rlp.de
|
|||||||
Created on: 30.11.20
|
Created on: 30.11.20
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
from konova.sub_settings.django_settings import env
|
||||||
|
|
||||||
INTERVENTION_IDENTIFIER_LENGTH = 6
|
INTERVENTION_IDENTIFIER_LENGTH = 6
|
||||||
INTERVENTION_IDENTIFIER_TEMPLATE = "EIV-{}"
|
INTERVENTION_IDENTIFIER_TEMPLATE = "EIV-{}"
|
||||||
|
|
||||||
@@ -14,7 +16,7 @@ INTERVENTION_LANIS_LAYER_NAME_UNRECORDED_OLD_ENTRY = "eiv_unrecorded_old_entries
|
|||||||
|
|
||||||
# EGON connection settings via rabbitmq
|
# EGON connection settings via rabbitmq
|
||||||
# NEEDED FOR BACKWARDS COMPATIBILITY
|
# NEEDED FOR BACKWARDS COMPATIBILITY
|
||||||
EGON_RABBITMQ_HOST = "CHANGE_ME"
|
EGON_RABBITMQ_HOST = env("EGON_RABBITMQ_HOST")
|
||||||
EGON_RABBITMQ_PORT = "CHANGE_ME"
|
EGON_RABBITMQ_PORT = env("EGON_RABBITMQ_PORT")
|
||||||
EGON_RABBITMQ_USER = "CHANGE_ME"
|
EGON_RABBITMQ_USER = env("EGON_RABBITMQ_USER")
|
||||||
EGON_RABBITMQ_PW = "CHANGE_ME"
|
EGON_RABBITMQ_PW = env("EGON_RABBITMQ_PW")
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import os
|
import os
|
||||||
|
|
||||||
from celery import Celery
|
from celery import Celery
|
||||||
|
from konova.sub_settings.django_settings import env
|
||||||
|
|
||||||
# Set the default Django settings module for the 'celery' program.
|
# Set the default Django settings module for the 'celery' program.
|
||||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'konova.settings')
|
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'konova.settings')
|
||||||
@@ -17,7 +18,7 @@ app.config_from_object('django.conf:settings', namespace='CELERY')
|
|||||||
app.autodiscover_tasks()
|
app.autodiscover_tasks()
|
||||||
|
|
||||||
# Declare redis as broker
|
# Declare redis as broker
|
||||||
app.conf.broker_url = 'redis://localhost:6379/0'
|
app.conf.broker_url = f'redis://{env("REDIS_HOST")}:{env.int("REDIS_PORT")}/0'
|
||||||
|
|
||||||
|
|
||||||
@app.task(bind=True)
|
@app.task(bind=True)
|
||||||
|
|||||||
54
konova/management/commands/send_to_egon.py
Normal file
54
konova/management/commands/send_to_egon.py
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
"""
|
||||||
|
Author: Michel Peltriaux
|
||||||
|
Organization: Struktur- und Genehmigungsdirektion Nord, Rhineland-Palatinate, Germany
|
||||||
|
Contact: ksp-servicestelle@sgdnord.rlp.de
|
||||||
|
Created on: 18.06.24
|
||||||
|
|
||||||
|
"""
|
||||||
|
from django.db.models import QuerySet
|
||||||
|
|
||||||
|
from intervention.models import Intervention
|
||||||
|
from konova.management.commands.setup import BaseKonovaCommand
|
||||||
|
|
||||||
|
|
||||||
|
class Command(BaseKonovaCommand):
|
||||||
|
help = "Send specific intervention entries to EGON if there are any payments on them"
|
||||||
|
|
||||||
|
def add_arguments(self, parser):
|
||||||
|
try:
|
||||||
|
parser.add_argument("--intervention-ids", type=str)
|
||||||
|
except ValueError as e:
|
||||||
|
self._write_error(f"Argument error: {e}")
|
||||||
|
exit(-1)
|
||||||
|
|
||||||
|
def __handle_arguments(self, options):
|
||||||
|
self.intervention_ids = options["intervention_ids"] or ""
|
||||||
|
self.intervention_ids = self.intervention_ids.split(",")
|
||||||
|
self.intervention_ids = [x.strip() for x in self.intervention_ids]
|
||||||
|
|
||||||
|
def handle(self, *args, **options):
|
||||||
|
try:
|
||||||
|
self.__handle_arguments(options)
|
||||||
|
interventions = self.get_interventions()
|
||||||
|
self.process_egon_sending(interventions)
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
self._break_line()
|
||||||
|
exit(-1)
|
||||||
|
|
||||||
|
def get_interventions(self) -> QuerySet:
|
||||||
|
"""
|
||||||
|
Getter for interventions, defined by parameter 'intervention-ids'
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
interventions (QuerySet): The interventions
|
||||||
|
"""
|
||||||
|
interventions = Intervention.objects.filter(
|
||||||
|
id__in=self.intervention_ids,
|
||||||
|
)
|
||||||
|
self._write_success(f"... Found {interventions.count()} interventions")
|
||||||
|
return interventions
|
||||||
|
|
||||||
|
def process_egon_sending(self, interventions: QuerySet):
|
||||||
|
for intervention in interventions:
|
||||||
|
intervention.send_data_to_egon()
|
||||||
|
self._write_warning(f"... {intervention.identifier} has been sent to EGON (if it has payments)")
|
||||||
@@ -18,7 +18,6 @@ from konova.sub_settings.proxy_settings import *
|
|||||||
from konova.sub_settings.sso_settings import *
|
from konova.sub_settings.sso_settings import *
|
||||||
from konova.sub_settings.table_settings import *
|
from konova.sub_settings.table_settings import *
|
||||||
from konova.sub_settings.lanis_settings import *
|
from konova.sub_settings.lanis_settings import *
|
||||||
from konova.sub_settings.wfs_parcel_settings import *
|
|
||||||
from konova.sub_settings.logging_settings import *
|
from konova.sub_settings.logging_settings import *
|
||||||
|
|
||||||
# Max upload size for POST forms
|
# Max upload size for POST forms
|
||||||
|
|||||||
@@ -1,78 +0,0 @@
|
|||||||
"""
|
|
||||||
Author: Michel Peltriaux
|
|
||||||
Organization: Struktur- und Genehmigungsdirektion Nord, Rhineland-Palatinate, Germany
|
|
||||||
Contact: michel.peltriaux@sgdnord.rlp.de
|
|
||||||
Created on: 17.08.21
|
|
||||||
|
|
||||||
"""
|
|
||||||
from django.http import HttpResponse
|
|
||||||
from django.urls import re_path
|
|
||||||
from django.views import View
|
|
||||||
from django.views.decorators.csrf import csrf_exempt
|
|
||||||
from itsdangerous import TimedSerializer
|
|
||||||
from simple_sso.sso_client.client import Client
|
|
||||||
|
|
||||||
from user.models import User
|
|
||||||
|
|
||||||
|
|
||||||
class PropagateView(View):
|
|
||||||
""" View used to receive propagated sso-server user data
|
|
||||||
|
|
||||||
"""
|
|
||||||
client = None
|
|
||||||
signer = None
|
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
|
||||||
super().__init__(*args, **kwargs)
|
|
||||||
self.signer = TimedSerializer(self.client.private_key)
|
|
||||||
|
|
||||||
@csrf_exempt
|
|
||||||
def dispatch(self, request, *args, **kwargs):
|
|
||||||
return super().dispatch(request, *args, **kwargs)
|
|
||||||
|
|
||||||
def post(self, request):
|
|
||||||
user_data = request.body
|
|
||||||
user_data = self.signer.loads(user_data)
|
|
||||||
self.client.build_user(user_data)
|
|
||||||
return HttpResponse(status=200)
|
|
||||||
|
|
||||||
|
|
||||||
class KonovaSSOClient(Client):
|
|
||||||
""" Konova specialized derivative of general sso.Client.
|
|
||||||
|
|
||||||
Adds some custom behaviour for konova usage.
|
|
||||||
|
|
||||||
"""
|
|
||||||
propagate_view = PropagateView
|
|
||||||
|
|
||||||
def get_urls(self):
|
|
||||||
urls = super().get_urls()
|
|
||||||
urls += re_path(r'^propagate/$', self.propagate_view.as_view(client=self), name='simple-sso-propagate'),
|
|
||||||
return urls
|
|
||||||
|
|
||||||
def build_user(self, user_data):
|
|
||||||
""" Creates a user or updates user data
|
|
||||||
|
|
||||||
Args:
|
|
||||||
user_data ():
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
user = User.objects.get(username=user_data['username'])
|
|
||||||
# Update user data, excluding some changes
|
|
||||||
skipable_attrs = {
|
|
||||||
"username",
|
|
||||||
"is_staff",
|
|
||||||
"is_superuser",
|
|
||||||
}
|
|
||||||
for _attr, _val in user_data.items():
|
|
||||||
if _attr in skipable_attrs:
|
|
||||||
continue
|
|
||||||
setattr(user, _attr, _val)
|
|
||||||
except User.DoesNotExist:
|
|
||||||
user = User(**user_data)
|
|
||||||
user.set_unusable_password()
|
|
||||||
user.save()
|
|
||||||
return user
|
|
||||||
@@ -10,6 +10,8 @@ For the full list of settings and their values, see
|
|||||||
https://docs.djangoproject.com/en/3.1/ref/settings/
|
https://docs.djangoproject.com/en/3.1/ref/settings/
|
||||||
"""
|
"""
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
import environ
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
from django.conf.locale.de import formats as de_formats
|
from django.conf.locale.de import formats as de_formats
|
||||||
|
|
||||||
@@ -24,32 +26,28 @@ BASE_DIR = os.path.dirname(
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
# Quick-start development settings - unsuitable for production
|
env = environ.Env()
|
||||||
# See https://docs.djangoproject.com/en/3.1/howto/deployment/checklist/
|
# Take environment variables from .env.dev file
|
||||||
|
environ.Env.read_env(os.path.join(BASE_DIR, '.env'))
|
||||||
|
|
||||||
# SECURITY WARNING: keep the secret key used in production secret!
|
# SECURITY WARNING: keep the secret key used in production secret!
|
||||||
SECRET_KEY = '5=9-)2)h$u9=!zrhia9=lj-2#cpcb8=#$7y+)l$5tto$3q(n_+'
|
SECRET_KEY = env("SECRET_KEY")
|
||||||
|
|
||||||
# SECURITY WARNING: don't run with debug turned on in production!
|
# SECURITY WARNING: don't run with debug turned on in production!
|
||||||
DEBUG = True
|
DEBUG = env.bool("DEBUG", default=False)
|
||||||
|
|
||||||
ADMINS = [
|
ADMINS = [x.split(':') for x in env.list('ADMINS')]
|
||||||
('KSP-Servicestelle', 'ksp-servicestelle@sgdnord.rlp.de'),
|
|
||||||
]
|
|
||||||
|
|
||||||
BASE_URL = "http://localhost:8001"
|
ALLOWED_HOSTS = env.list("ALLOWED_HOSTS")
|
||||||
|
|
||||||
ALLOWED_HOSTS = [
|
BASE_URL = env("BASE_URL")
|
||||||
"127.0.0.1",
|
|
||||||
"localhost",
|
|
||||||
]
|
|
||||||
|
|
||||||
CSRF_TRUSTED_ORIGINS = [
|
CSRF_TRUSTED_ORIGINS = [
|
||||||
"http://localhost", # not only host but schema (http/s) as well!
|
BASE_URL
|
||||||
]
|
]
|
||||||
|
|
||||||
# Authentication settings
|
# Authentication settings
|
||||||
LOGIN_URL = "/login/"
|
LOGIN_URL = "/oauth/login/"
|
||||||
|
|
||||||
# Session settings
|
# Session settings
|
||||||
SESSION_COOKIE_AGE = 60 * 60 # 60 minutes
|
SESSION_COOKIE_AGE = 60 * 60 # 60 minutes
|
||||||
@@ -83,10 +81,6 @@ INSTALLED_APPS = [
|
|||||||
'analysis',
|
'analysis',
|
||||||
'api',
|
'api',
|
||||||
]
|
]
|
||||||
if DEBUG:
|
|
||||||
INSTALLED_APPS += [
|
|
||||||
'debug_toolbar',
|
|
||||||
]
|
|
||||||
|
|
||||||
MIDDLEWARE = [
|
MIDDLEWARE = [
|
||||||
'django.middleware.security.SecurityMiddleware',
|
'django.middleware.security.SecurityMiddleware',
|
||||||
@@ -98,10 +92,6 @@ MIDDLEWARE = [
|
|||||||
'django.contrib.messages.middleware.MessageMiddleware',
|
'django.contrib.messages.middleware.MessageMiddleware',
|
||||||
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
||||||
]
|
]
|
||||||
if DEBUG:
|
|
||||||
MIDDLEWARE += [
|
|
||||||
"debug_toolbar.middleware.DebugToolbarMiddleware",
|
|
||||||
]
|
|
||||||
|
|
||||||
ROOT_URLCONF = 'konova.urls'
|
ROOT_URLCONF = 'konova.urls'
|
||||||
|
|
||||||
@@ -131,10 +121,11 @@ WSGI_APPLICATION = 'konova.wsgi.application'
|
|||||||
DATABASES = {
|
DATABASES = {
|
||||||
'default': {
|
'default': {
|
||||||
'ENGINE': 'django.contrib.gis.db.backends.postgis',
|
'ENGINE': 'django.contrib.gis.db.backends.postgis',
|
||||||
'NAME': 'konova',
|
'NAME': env("DB_NAME"),
|
||||||
'USER': 'postgres',
|
'USER': env("DB_USER"),
|
||||||
'HOST': '127.0.0.1',
|
'PASSWORD': env("DB_PASSWORD"),
|
||||||
'PORT': '5432',
|
'HOST': env("DB_HOST"),
|
||||||
|
'PORT': env("DB_PORT"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"
|
DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"
|
||||||
@@ -201,28 +192,6 @@ STATICFILES_DIRS = [
|
|||||||
os.path.join(BASE_DIR, 'templates/map/client/libs'), # NETGIS map client files
|
os.path.join(BASE_DIR, 'templates/map/client/libs'), # NETGIS map client files
|
||||||
]
|
]
|
||||||
|
|
||||||
# DJANGO DEBUG TOOLBAR
|
|
||||||
INTERNAL_IPS = [
|
|
||||||
"127.0.0.1"
|
|
||||||
]
|
|
||||||
DEBUG_TOOLBAR_CONFIG = {
|
|
||||||
"DISABLE_PANELS": {
|
|
||||||
'debug_toolbar.panels.versions.VersionsPanel',
|
|
||||||
'debug_toolbar.panels.timer.TimerPanel',
|
|
||||||
'debug_toolbar.panels.settings.SettingsPanel',
|
|
||||||
'debug_toolbar.panels.headers.HeadersPanel',
|
|
||||||
'debug_toolbar.panels.request.RequestPanel',
|
|
||||||
'debug_toolbar.panels.sql.SQLPanel',
|
|
||||||
'debug_toolbar.panels.staticfiles.StaticFilesPanel',
|
|
||||||
'debug_toolbar.panels.templates.TemplatesPanel',
|
|
||||||
'debug_toolbar.panels.cache.CachePanel',
|
|
||||||
'debug_toolbar.panels.signals.SignalsPanel',
|
|
||||||
'debug_toolbar.panels.logging.LoggingPanel',
|
|
||||||
'debug_toolbar.panels.redirects.RedirectsPanel',
|
|
||||||
'debug_toolbar.panels.profiling.ProfilingPanel',
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# EMAIL (see https://docs.djangoproject.com/en/dev/topics/email/)
|
# EMAIL (see https://docs.djangoproject.com/en/dev/topics/email/)
|
||||||
|
|
||||||
# CHANGE_ME !!! ONLY FOR DEVELOPMENT !!!
|
# CHANGE_ME !!! ONLY FOR DEVELOPMENT !!!
|
||||||
@@ -230,13 +199,10 @@ if DEBUG:
|
|||||||
EMAIL_BACKEND = 'django.core.mail.backends.filebased.EmailBackend'
|
EMAIL_BACKEND = 'django.core.mail.backends.filebased.EmailBackend'
|
||||||
EMAIL_FILE_PATH = '/tmp/app-messages' # change this to a proper location
|
EMAIL_FILE_PATH = '/tmp/app-messages' # change this to a proper location
|
||||||
|
|
||||||
DEFAULT_FROM_EMAIL = "service@ksp.de" # The default email address for the 'from' element
|
DEFAULT_FROM_EMAIL = env("DEFAULT_FROM_EMAIL") # The default email address for the 'from' element
|
||||||
SERVER_EMAIL = DEFAULT_FROM_EMAIL # The default email sender address, which is used by Django to send errors via mail
|
SERVER_EMAIL = DEFAULT_FROM_EMAIL # The default email sender address, which is used by Django to send errors via mail
|
||||||
EMAIL_HOST = "localhost"
|
EMAIL_HOST = env("SMTP_HOST")
|
||||||
EMAIL_REPLY_TO = "ksp-servicestelle@sgdnord.rlp.de"
|
EMAIL_REPLY_TO = env("REPLY_TO_ADDR")
|
||||||
SUPPORT_MAIL_RECIPIENT = EMAIL_REPLY_TO
|
EMAIL_PORT = env("SMTP_PORT")
|
||||||
EMAIL_PORT = "25"
|
|
||||||
#EMAIL_HOST_USER = ""
|
|
||||||
#EMAIL_HOST_PASSWORD = ""
|
|
||||||
EMAIL_USE_TLS = False
|
EMAIL_USE_TLS = False
|
||||||
EMAIL_USE_SSL = False
|
EMAIL_USE_SSL = False
|
||||||
|
|||||||
@@ -5,12 +5,13 @@ Contact: michel.peltriaux@sgdnord.rlp.de
|
|||||||
Created on: 31.01.22
|
Created on: 31.01.22
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
from konova.sub_settings.django_settings import env
|
||||||
|
|
||||||
proxy = ""
|
proxy = env("PROXY")
|
||||||
PROXIES = {
|
PROXIES = {
|
||||||
"http": proxy,
|
"http": proxy,
|
||||||
"https": proxy,
|
"https": proxy,
|
||||||
}
|
}
|
||||||
|
|
||||||
CLIENT_PROXY_AUTH_USER = "CHANGE_ME"
|
GEOPORTAL_RLP_USER = env("GEOPORTAL_RLP_USER")
|
||||||
CLIENT_PROXY_AUTH_PASSWORD = "CHANGE_ME"
|
GEOPORTAL_RLP_PASSWORD = env("GEOPORTAL_RLP_PASSWORD")
|
||||||
|
|||||||
@@ -5,7 +5,8 @@ Contact: ksp-servicestelle@sgdnord.rlp.de
|
|||||||
Created on: 14.12.22
|
Created on: 14.12.22
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
from konova.sub_settings.django_settings import env
|
||||||
|
|
||||||
base_url = "http://127.0.0.1:8002"
|
base_url = env("SCHNEIDER_BASE_URL")
|
||||||
auth_header = "auth"
|
auth_header = env("SCHNEIDER_AUTH_HEADER")
|
||||||
auth_header_token = "CHANGE_ME"
|
auth_header_token = env("SCHNEIDER_AUTH_TOKEN")
|
||||||
|
|||||||
@@ -5,9 +5,14 @@ Contact: michel.peltriaux@sgdnord.rlp.de
|
|||||||
Created on: 31.01.22
|
Created on: 31.01.22
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
from konova.sub_settings.django_settings import env
|
||||||
|
|
||||||
# SSO settings
|
# SSO settings
|
||||||
SSO_SERVER_BASE = "http://127.0.0.1:8000/"
|
SSO_SERVER_BASE = env("SSO_SERVER_BASE_URL")
|
||||||
SSO_SERVER = f"{SSO_SERVER_BASE}sso/"
|
SSO_SERVER = f"{SSO_SERVER_BASE}sso/"
|
||||||
SSO_PRIVATE_KEY = "CHANGE_ME"
|
|
||||||
SSO_PUBLIC_KEY = "CHANGE_ME"
|
# OAuth settings
|
||||||
|
OAUTH_CODE_VERIFIER = env("OAUTH_CODE_VERIFIER")
|
||||||
|
|
||||||
|
OAUTH_CLIENT_ID = env("OAUTH_CLIENT_ID")
|
||||||
|
OAUTH_CLIENT_SECRET = env("OAUTH_CLIENT_SECRET")
|
||||||
|
|||||||
@@ -1,12 +0,0 @@
|
|||||||
"""
|
|
||||||
Author: Michel Peltriaux
|
|
||||||
Organization: Struktur- und Genehmigungsdirektion Nord, Rhineland-Palatinate, Germany
|
|
||||||
Contact: michel.peltriaux@sgdnord.rlp.de
|
|
||||||
Created on: 31.01.22
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
# Parcel WFS settings
|
|
||||||
PARCEL_WFS_BASE_URL = "https://www.geoportal.rlp.de/registry/wfs/519"
|
|
||||||
PARCEL_WFS_USER = "ksp"
|
|
||||||
PARCEL_WFS_PW = "CHANGE_ME"
|
|
||||||
@@ -7,7 +7,7 @@ from django.core.exceptions import ObjectDoesNotExist
|
|||||||
|
|
||||||
@shared_task
|
@shared_task
|
||||||
def celery_update_parcels(geometry_id: str, recheck: bool = True):
|
def celery_update_parcels(geometry_id: str, recheck: bool = True):
|
||||||
from konova.models import Geometry, ParcelIntersection
|
from konova.models import Geometry
|
||||||
try:
|
try:
|
||||||
geom = Geometry.objects.get(id=geometry_id)
|
geom = Geometry.objects.get(id=geometry_id)
|
||||||
geom.parcels.clear()
|
geom.parcels.clear()
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="scroll-150 font-italic">
|
<div class="scroll-150 font-italic">
|
||||||
{{obj.comment}}
|
{{obj.comment|linebreaks}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -509,7 +509,7 @@ class BaseViewTestCase(BaseTestCase):
|
|||||||
|
|
||||||
def setUp(self) -> None:
|
def setUp(self) -> None:
|
||||||
super().setUp()
|
super().setUp()
|
||||||
self.login_url = reverse("simple-sso-login")
|
self.login_url = reverse("oauth-login")
|
||||||
|
|
||||||
def assert_url_success(self, client: Client, urls: list):
|
def assert_url_success(self, client: Client, urls: list):
|
||||||
""" Assert for all given urls a direct 200 response
|
""" Assert for all given urls a direct 200 response
|
||||||
|
|||||||
@@ -13,21 +13,19 @@ Including another URLconf
|
|||||||
1. Import the include() function: from django.urls import include, path
|
1. Import the include() function: from django.urls import include, path
|
||||||
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
|
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
|
||||||
"""
|
"""
|
||||||
import debug_toolbar
|
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
from django.urls import path, include
|
from django.urls import path, include
|
||||||
|
|
||||||
from konova.settings import SSO_SERVER, SSO_PUBLIC_KEY, SSO_PRIVATE_KEY, DEBUG
|
|
||||||
from konova.sso.sso import KonovaSSOClient
|
|
||||||
from konova.views.logout import LogoutView
|
from konova.views.logout import LogoutView
|
||||||
from konova.views.geometry import GeomParcelsView, GeomParcelsContentView
|
from konova.views.geometry import GeomParcelsView, GeomParcelsContentView
|
||||||
from konova.views.home import HomeView
|
from konova.views.home import HomeView
|
||||||
from konova.views.map_proxy import ClientProxyParcelSearch, ClientProxyParcelWFS
|
from konova.views.map_proxy import ClientProxyParcelSearch, ClientProxyParcelWFS
|
||||||
|
from konova.views.oauth import OAuthLoginView, OAuthCallbackView
|
||||||
|
|
||||||
sso_client = KonovaSSOClient(SSO_SERVER, SSO_PUBLIC_KEY, SSO_PRIVATE_KEY)
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path('admin/', admin.site.urls),
|
path('admin/', admin.site.urls),
|
||||||
path('login/', include(sso_client.get_urls())),
|
path('oauth/callback/', OAuthCallbackView.as_view(), name="oauth-callback"),
|
||||||
|
path('oauth/login/', OAuthLoginView.as_view(), name="oauth-login"),
|
||||||
path('logout/', LogoutView.as_view(), name="logout"),
|
path('logout/', LogoutView.as_view(), name="logout"),
|
||||||
path('', HomeView.as_view(), name="home"),
|
path('', HomeView.as_view(), name="home"),
|
||||||
path('intervention/', include("intervention.urls")),
|
path('intervention/', include("intervention.urls")),
|
||||||
@@ -44,10 +42,5 @@ urlpatterns = [
|
|||||||
path('client/proxy/wfs', ClientProxyParcelWFS.as_view(), name="client-proxy-wfs"),
|
path('client/proxy/wfs', ClientProxyParcelWFS.as_view(), name="client-proxy-wfs"),
|
||||||
]
|
]
|
||||||
|
|
||||||
if DEBUG:
|
|
||||||
urlpatterns += [
|
|
||||||
path('__debug__/', include(debug_toolbar.urls)),
|
|
||||||
]
|
|
||||||
|
|
||||||
handler404 = "konova.views.error.get_404_view"
|
handler404 = "konova.views.error.get_404_view"
|
||||||
handler500 = "konova.views.error.get_500_view"
|
handler500 = "konova.views.error.get_500_view"
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ from django.core.mail import send_mail
|
|||||||
from django.template.loader import render_to_string
|
from django.template.loader import render_to_string
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
from konova.sub_settings.django_settings import DEFAULT_FROM_EMAIL, EMAIL_REPLY_TO, SUPPORT_MAIL_RECIPIENT
|
from konova.sub_settings.django_settings import DEFAULT_FROM_EMAIL, EMAIL_REPLY_TO
|
||||||
|
|
||||||
|
|
||||||
class Mailer:
|
class Mailer:
|
||||||
@@ -416,7 +416,7 @@ class Mailer:
|
|||||||
"EMAIL_REPLY_TO": EMAIL_REPLY_TO,
|
"EMAIL_REPLY_TO": EMAIL_REPLY_TO,
|
||||||
}
|
}
|
||||||
msg = render_to_string("email/api/verify_token.html", context)
|
msg = render_to_string("email/api/verify_token.html", context)
|
||||||
user_mail_address = [SUPPORT_MAIL_RECIPIENT]
|
user_mail_address = [EMAIL_REPLY_TO]
|
||||||
self.send(
|
self.send(
|
||||||
user_mail_address,
|
user_mail_address,
|
||||||
_("Request for new API token"),
|
_("Request for new API token"),
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ from json import JSONDecodeError
|
|||||||
import requests
|
import requests
|
||||||
|
|
||||||
from konova.sub_settings import schneider_settings
|
from konova.sub_settings import schneider_settings
|
||||||
|
from konova.sub_settings.proxy_settings import PROXIES
|
||||||
|
|
||||||
|
|
||||||
class ParcelFetcher:
|
class ParcelFetcher:
|
||||||
@@ -43,6 +44,7 @@ class ParcelFetcher:
|
|||||||
|
|
||||||
response = requests.post(
|
response = requests.post(
|
||||||
url=post_url,
|
url=post_url,
|
||||||
|
proxies=PROXIES,
|
||||||
data=self.geojson,
|
data=self.geojson,
|
||||||
headers={
|
headers={
|
||||||
self.auth_header: self.auth_header_token
|
self.auth_header: self.auth_header_token
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ from django.utils.translation import gettext_lazy as _
|
|||||||
|
|
||||||
from requests.auth import HTTPDigestAuth
|
from requests.auth import HTTPDigestAuth
|
||||||
|
|
||||||
from konova.sub_settings.proxy_settings import PROXIES, CLIENT_PROXY_AUTH_USER, CLIENT_PROXY_AUTH_PASSWORD
|
from konova.sub_settings.proxy_settings import PROXIES, GEOPORTAL_RLP_USER, GEOPORTAL_RLP_PASSWORD
|
||||||
|
|
||||||
|
|
||||||
class BaseClientProxyView(View):
|
class BaseClientProxyView(View):
|
||||||
@@ -90,7 +90,7 @@ class ClientProxyParcelWFS(BaseClientProxyView):
|
|||||||
url = f"{base_url}?{urlencode(params, doseq=True)}"
|
url = f"{base_url}?{urlencode(params, doseq=True)}"
|
||||||
|
|
||||||
url = url.replace("typename", "typenames")
|
url = url.replace("typename", "typenames")
|
||||||
auth = HTTPDigestAuth(CLIENT_PROXY_AUTH_USER, CLIENT_PROXY_AUTH_PASSWORD)
|
auth = HTTPDigestAuth(GEOPORTAL_RLP_USER, GEOPORTAL_RLP_PASSWORD)
|
||||||
|
|
||||||
content, response_code = self.perform_url_call(url, auth=auth)
|
content, response_code = self.perform_url_call(url, auth=auth)
|
||||||
error_detected = response_code != 200
|
error_detected = response_code != 200
|
||||||
|
|||||||
125
konova/views/oauth.py
Normal file
125
konova/views/oauth.py
Normal file
@@ -0,0 +1,125 @@
|
|||||||
|
"""
|
||||||
|
Author: Michel Peltriaux
|
||||||
|
Organization: Struktur- und Genehmigungsdirektion Nord, Rhineland-Palatinate, Germany
|
||||||
|
Contact: ksp-servicestelle@sgdnord.rlp.de
|
||||||
|
Created on: 26.04.24
|
||||||
|
|
||||||
|
"""
|
||||||
|
import base64
|
||||||
|
import hashlib
|
||||||
|
from urllib.parse import urlencode
|
||||||
|
|
||||||
|
import requests
|
||||||
|
from django.contrib.auth import login
|
||||||
|
from django.http import HttpRequest
|
||||||
|
from django.shortcuts import redirect
|
||||||
|
from django.urls import reverse
|
||||||
|
from django.utils.timezone import now
|
||||||
|
from django.views import View
|
||||||
|
|
||||||
|
from api.models import OAuthToken
|
||||||
|
from konova.sub_settings.django_settings import BASE_URL
|
||||||
|
from konova.sub_settings.sso_settings import SSO_SERVER_BASE, OAUTH_CODE_VERIFIER, OAUTH_CLIENT_ID, OAUTH_CLIENT_SECRET
|
||||||
|
|
||||||
|
|
||||||
|
class OAuthLoginView(View):
|
||||||
|
"""
|
||||||
|
Starts OAuth Login procedure
|
||||||
|
-> AnonymousUser is redirected to SSO component using specific parameters
|
||||||
|
-> After successful login (in SSO component), user will be redirected to a specific callback url (OAuthCallbackView)
|
||||||
|
-> Callback view uses retrieved authorization token to get a proper access token from SSO component
|
||||||
|
-> SSO component answers with access token
|
||||||
|
-> OAuthCallbackView uses token in Authorization header to access user data of logged-in user in SSO component
|
||||||
|
-> OAuthCallbackView creates/updates user
|
||||||
|
-> OAuthCallbackView logs in user and redirects to default home view
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __create_code_challenge(self):
|
||||||
|
"""
|
||||||
|
Creates a code verifier and code challenge for extra security.
|
||||||
|
See https://django-oauth-toolkit.readthedocs.io/en/latest/getting_started.html#authorization-code for further
|
||||||
|
information
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
"""
|
||||||
|
code_verifier = OAUTH_CODE_VERIFIER
|
||||||
|
|
||||||
|
code_challenge = hashlib.sha256(code_verifier.encode('utf-8')).digest()
|
||||||
|
code_challenge = base64.urlsafe_b64encode(code_challenge).decode('utf-8').replace('=', '')
|
||||||
|
return code_verifier, code_challenge
|
||||||
|
|
||||||
|
def get(self, request: HttpRequest, *args, **kwargs):
|
||||||
|
"""
|
||||||
|
Redirects user to OAuth SSO webservice for credential based login there
|
||||||
|
|
||||||
|
Args:
|
||||||
|
request ():
|
||||||
|
*args ():
|
||||||
|
**kwargs ():
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
"""
|
||||||
|
oauth_authentication_code_url = f"{SSO_SERVER_BASE}o/authorize/"
|
||||||
|
redirect_uri = f'{BASE_URL}{reverse("oauth-callback")}'
|
||||||
|
|
||||||
|
code_verifier, code_challenge = self.__create_code_challenge()
|
||||||
|
|
||||||
|
urlencode_params = urlencode(
|
||||||
|
{
|
||||||
|
"response_type": "code",
|
||||||
|
"code_challenge": code_challenge,
|
||||||
|
"code_challenge_method": "S256",
|
||||||
|
"client_id": OAUTH_CLIENT_ID,
|
||||||
|
"redirect_uri": redirect_uri,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
url = f"{oauth_authentication_code_url}?{urlencode_params}"
|
||||||
|
return redirect(url)
|
||||||
|
|
||||||
|
|
||||||
|
class OAuthCallbackView(View):
|
||||||
|
"""
|
||||||
|
Callback view for OAuth2.0 authentication token.
|
||||||
|
Authentication tokens will be exchanged for access token.
|
||||||
|
Access Token will be used for fetching user data from SSO component.
|
||||||
|
User data will be used for creating/updating user data inside this app.
|
||||||
|
User will be logged-in and redirected to default home view.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
def get(self, request: HttpRequest, *args, **kwargs):
|
||||||
|
authentication_code = request.GET.get("code")
|
||||||
|
oauth_acces_token_url = f"{SSO_SERVER_BASE}o/token/"
|
||||||
|
|
||||||
|
callback_url = f'{BASE_URL}{reverse("oauth-callback")}'
|
||||||
|
|
||||||
|
params = {
|
||||||
|
"grant_type": "authorization_code",
|
||||||
|
"code": authentication_code,
|
||||||
|
"redirect_uri": callback_url,
|
||||||
|
"code_verifier": OAUTH_CODE_VERIFIER,
|
||||||
|
"client_id": OAUTH_CLIENT_ID,
|
||||||
|
"client_secret": OAUTH_CLIENT_SECRET
|
||||||
|
}
|
||||||
|
access_code_response = requests.post(
|
||||||
|
oauth_acces_token_url,
|
||||||
|
data=params
|
||||||
|
)
|
||||||
|
received_on = now()
|
||||||
|
|
||||||
|
access_code_response_body = access_code_response.content.decode("utf-8")
|
||||||
|
status_code_invalid = access_code_response.status_code != 200
|
||||||
|
if status_code_invalid:
|
||||||
|
raise RuntimeError(f"OAuth access token could not be fetched: {access_code_response.text}")
|
||||||
|
|
||||||
|
oauth_access_token = OAuthToken.from_access_token_response(access_code_response_body, received_on)
|
||||||
|
oauth_access_token.save()
|
||||||
|
user = oauth_access_token.update_and_get_user()
|
||||||
|
user.oauth_replace_token(oauth_access_token)
|
||||||
|
|
||||||
|
login(request, user)
|
||||||
|
return redirect("home")
|
||||||
|
|
||||||
@@ -4,55 +4,62 @@ async-timeout==4.0.3
|
|||||||
beautifulsoup4==4.13.0b2
|
beautifulsoup4==4.13.0b2
|
||||||
billiard==4.2.0
|
billiard==4.2.0
|
||||||
cached-property==1.5.2
|
cached-property==1.5.2
|
||||||
celery==5.4.0rc2
|
celery==5.4.0
|
||||||
certifi==2024.2.2
|
certifi==2024.7.4
|
||||||
|
cffi==1.17.0rc1
|
||||||
chardet==5.2.0
|
chardet==5.2.0
|
||||||
charset-normalizer==3.3.2
|
charset-normalizer==3.3.2
|
||||||
click==8.1.7
|
click==8.1.7
|
||||||
click-didyoumean==0.3.1
|
click-didyoumean==0.3.1
|
||||||
click-plugins==1.1.1
|
click-plugins==1.1.1
|
||||||
click-repl==0.3.0
|
click-repl==0.3.0
|
||||||
coverage==7.4.4
|
coverage==7.5.4
|
||||||
|
cryptography==42.0.8
|
||||||
Deprecated==1.2.14
|
Deprecated==1.2.14
|
||||||
Django==5.0.4
|
Django==5.0.7
|
||||||
django-autocomplete-light==3.11.0
|
django-autocomplete-light==3.11.0
|
||||||
django-bootstrap-modal-forms==3.0.4
|
django-bootstrap-modal-forms==3.0.4
|
||||||
django-bootstrap4==24.1
|
django-bootstrap4==24.3
|
||||||
django-debug-toolbar==4.3.0
|
|
||||||
django-environ==0.11.2
|
django-environ==0.11.2
|
||||||
django-filter==24.2
|
django-filter==24.2
|
||||||
django-fontawesome-5==1.0.18
|
django-fontawesome-5==1.0.18
|
||||||
|
django-oauth-toolkit==2.4.0
|
||||||
django-simple-sso==1.2.0
|
django-simple-sso==1.2.0
|
||||||
django-tables2==2.7.0
|
django-tables2==2.7.0
|
||||||
et-xmlfile==1.1.0
|
et-xmlfile==1.1.0
|
||||||
|
gunicorn==22.0.0
|
||||||
idna==3.7
|
idna==3.7
|
||||||
importlib_metadata==7.1.0
|
importlib_metadata==8.0.0
|
||||||
itsdangerous==2.1.2
|
itsdangerous==0.24
|
||||||
kombu==5.3.7
|
jwcrypto==1.5.6
|
||||||
|
kombu==5.4.0rc1
|
||||||
|
oauthlib==3.2.2
|
||||||
openpyxl==3.2.0b1
|
openpyxl==3.2.0b1
|
||||||
packaging==24.0
|
packaging==24.1
|
||||||
pika==1.3.2
|
pika==1.3.2
|
||||||
prompt-toolkit==3.0.43
|
pillow==10.4.0
|
||||||
psycopg==3.1.18
|
prompt_toolkit==3.0.47
|
||||||
psycopg-binary==3.1.18
|
psycopg==3.2.1
|
||||||
|
psycopg-binary==3.2.1
|
||||||
|
pycparser==2.22
|
||||||
pyparsing==3.1.2
|
pyparsing==3.1.2
|
||||||
pypng==0.20220715.0
|
pypng==0.20220715.0
|
||||||
pyproj==3.6.1
|
pyproj==3.6.1
|
||||||
python-dateutil==2.9.0.post0
|
python-dateutil==2.9.0.post0
|
||||||
pytz==2024.1
|
pytz==2024.1
|
||||||
PyYAML==6.0.1
|
PyYAML==6.0.2rc1
|
||||||
qrcode==7.3.1
|
qrcode==7.3.1
|
||||||
redis==5.1.0b4
|
redis==5.1.0b6
|
||||||
requests==2.31.0
|
requests<2.32.0
|
||||||
six==1.16.0
|
six==1.16.0
|
||||||
soupsieve==2.5
|
soupsieve==2.5
|
||||||
sqlparse==0.4.4
|
sqlparse==0.5.0
|
||||||
typing_extensions==4.11.0
|
typing_extensions==4.12.2
|
||||||
tzdata==2024.1
|
tzdata==2024.1
|
||||||
urllib3==2.2.1
|
urllib3==2.2.2
|
||||||
vine==5.1.0
|
vine==5.1.0
|
||||||
wcwidth==0.2.13
|
wcwidth==0.2.13
|
||||||
webservices==0.7
|
webservices==0.7
|
||||||
wrapt==1.16.0
|
wrapt==1.16.0
|
||||||
xmltodict==0.13.0
|
xmltodict==0.13.0
|
||||||
zipp==3.18.1
|
zipp==3.19.2
|
||||||
|
|||||||
@@ -112,7 +112,7 @@
|
|||||||
},
|
},
|
||||||
"import":
|
"import":
|
||||||
{
|
{
|
||||||
"geopackageLibURL": "/libs/geopackage/4.2.3/"
|
"geopackageLibURL": "/static/libs/geopackage/4.2.3/"
|
||||||
},
|
},
|
||||||
"export":
|
"export":
|
||||||
{
|
{
|
||||||
|
|||||||
44
templates/map/client/netgis.min.js
vendored
44
templates/map/client/netgis.min.js
vendored
@@ -16,7 +16,7 @@ netgis.Client=function(a,b){this.build="20220826";this.debug=!1;netgis.util.isSt
|
|||||||
this.hideLoader()};netgis.Client.Layers=Object.freeze({PARCEL_DISTRICTS:"parcel-districts",PARCEL_FIELDS:"parcel-fields",PARCEL_FEATURES:"parcel-features",EDIT_LAYER:"edit-layer",PREVIEW_LAYER:"preview-layer"});netgis.Client.prototype.applyConfig=function(a){this.createModules();this.load();this.invoke(netgis.Events.CONTEXT_UPDATE,a);this.initModules(a);this.initConfig(a);this.initOutput(a);this.initEvents();this.importLayers={};this.setMode(netgis.Modes.VIEW)};
|
this.hideLoader()};netgis.Client.Layers=Object.freeze({PARCEL_DISTRICTS:"parcel-districts",PARCEL_FIELDS:"parcel-fields",PARCEL_FEATURES:"parcel-features",EDIT_LAYER:"edit-layer",PREVIEW_LAYER:"preview-layer"});netgis.Client.prototype.applyConfig=function(a){this.createModules();this.load();this.invoke(netgis.Events.CONTEXT_UPDATE,a);this.initModules(a);this.initConfig(a);this.initOutput(a);this.initEvents();this.importLayers={};this.setMode(netgis.Modes.VIEW)};
|
||||||
netgis.Client.prototype.initElements=function(){};
|
netgis.Client.prototype.initElements=function(){};
|
||||||
netgis.Client.prototype.initModules=function(a){this.map=new netgis.MapOpenLayers(a);this.map.attach(this.root);this.controls=new netgis.Controls;this.controls.attach(this.root);this.layerPanel=new netgis.Panel("Inhalte");this.layerPanel.attach(this.root);this.layerTree=new netgis.Tree;this.layerTree.container.style.position="absolute";this.layerTree.container.style.width="100%";this.layerTree.container.style.top="12mm";this.layerTree.container.style.bottom="6mm";this.layerTree.container.style.overflow=
|
netgis.Client.prototype.initModules=function(a){this.map=new netgis.MapOpenLayers(a);this.map.attach(this.root);this.controls=new netgis.Controls;this.controls.attach(this.root);this.layerPanel=new netgis.Panel("Inhalte");this.layerPanel.attach(this.root);this.layerTree=new netgis.Tree;this.layerTree.container.style.position="absolute";this.layerTree.container.style.width="100%";this.layerTree.container.style.top="12mm";this.layerTree.container.style.bottom="6mm";this.layerTree.container.style.overflow=
|
||||||
"auto";this.layerTree.attach(this.layerPanel.container);this.toolboxPanel=new netgis.Panel("Werkzeuge");this.toolboxPanel.attach(this.root);this.toolbox=new netgis.Toolbox(a);this.toolbox.attach(this.toolboxPanel.container);this.searchPlace=new netgis.SearchPlace(a);this.searchPlace.attach(this.root);this.parcelPanel=new netgis.Panel("Flurst\u00fccks-Suche");this.parcelPanel.container.style.minWidth="92mm";this.parcelPanel.attach(this.root);this.searchParcel=new netgis.SearchParcel(a);this.searchParcel.attach(this.parcelPanel.container);
|
"auto";this.layerTree.attach(this.layerPanel.container);this.toolboxPanel=new netgis.Panel("Werkzeuge");this.toolboxPanel.attach(this.root);this.toolbox=new netgis.Toolbox(a);this.toolbox.attach(this.toolboxPanel.container);this.searchPlace=new netgis.SearchPlace(a);this.searchPlace.attach(this.root);this.parcelPanel=new netgis.Panel("Flurst\u00fccks-Suche");this.parcelPanel.container.style.minWidth="92mm";this.parcelPanel.attach(this.root);this.searchParcel=new netgis.SearchParcel(a,this);this.searchParcel.attach(this.parcelPanel.container);
|
||||||
this.importModal=new netgis.Modal("Ebene hinzuf\u00fcgen");this.importModal.container.classList.add("netgis-import");this.importModal.attach(this.root);a=document.createElement("div");a.className="netgis-content netgis-form netgis-noselect";this.importModal.content.appendChild(a);var b=document.createElement("label");b.innerHTML="Dateiformat:";a.appendChild(b);var c=document.createElement("select");c.innerHTML="<option value='geojson'>GeoJSON</option><option value='gml'>GML</option><option value='gpkg'>GeoPackage</option><option value='shp'>Shapefile (Zip)</option><option value='spatialite'>Spatialite</option>";
|
this.importModal=new netgis.Modal("Ebene hinzuf\u00fcgen");this.importModal.container.classList.add("netgis-import");this.importModal.attach(this.root);a=document.createElement("div");a.className="netgis-content netgis-form netgis-noselect";this.importModal.content.appendChild(a);var b=document.createElement("label");b.innerHTML="Dateiformat:";a.appendChild(b);var c=document.createElement("select");c.innerHTML="<option value='geojson'>GeoJSON</option><option value='gml'>GML</option><option value='gpkg'>GeoPackage</option><option value='shp'>Shapefile (Zip)</option><option value='spatialite'>Spatialite</option>";
|
||||||
b.addEventListener("change",this.onImportFileTypeChange.bind(this));b.appendChild(c);this.importFileSelect=c;b=document.createElement("div");b.innerHTML="<h3>Unterst\u00fctzte Koordinatensysteme:</h3><ul><li>World Geodetic System 1984 (EPSG:4326)</li><li>ETRS89 / UTM zone 32N (EPSG:25832)</li></ul>";a.appendChild(b);b=document.createElement("label");b.innerHTML="Datei ausw\u00e4hlen/ablegen:";a.appendChild(b);c=document.createElement("input");c.className="netgis-color-d";c.setAttribute("type","file");
|
b.addEventListener("change",this.onImportFileTypeChange.bind(this));b.appendChild(c);this.importFileSelect=c;b=document.createElement("div");b.innerHTML="<h3>Unterst\u00fctzte Koordinatensysteme:</h3><ul><li>World Geodetic System 1984 (EPSG:4326)</li><li>ETRS89 / UTM zone 32N (EPSG:25832)</li></ul>";a.appendChild(b);b=document.createElement("label");b.innerHTML="Datei ausw\u00e4hlen/ablegen:";a.appendChild(b);c=document.createElement("input");c.className="netgis-color-d";c.setAttribute("type","file");
|
||||||
c.setAttribute("accept",".geojson,.json");b.appendChild(c);this.importFileInput=c;b=document.createElement("button");b.setAttribute("type","button");b.className="netgis-button netgis-center netgis-color-a netgis-hover-c netgis-shadow";b.innerHTML="<i class='netgis-icon fas fa-check'></i><span>Hinzuf\u00fcgen</span>";b.addEventListener("click",this.onImportFileClick.bind(this));a.appendChild(b);this.importServiceModal=new netgis.Modal("Dienst hinzuf\u00fcgen");this.importServiceModal.container.classList.add("netgis-import");
|
c.setAttribute("accept",".geojson,.json");b.appendChild(c);this.importFileInput=c;b=document.createElement("button");b.setAttribute("type","button");b.className="netgis-button netgis-center netgis-color-a netgis-hover-c netgis-shadow";b.innerHTML="<i class='netgis-icon fas fa-check'></i><span>Hinzuf\u00fcgen</span>";b.addEventListener("click",this.onImportFileClick.bind(this));a.appendChild(b);this.importServiceModal=new netgis.Modal("Dienst hinzuf\u00fcgen");this.importServiceModal.container.classList.add("netgis-import");
|
||||||
@@ -53,15 +53,16 @@ netgis.Client.prototype.onLayersToggle=function(a){this.layerPanel.toggle();this
|
|||||||
netgis.Client.prototype.onLayerTreeItemChange=function(a){var b=a.detail.id;a=a.detail.checked;switch(b){default:for(var c=this.config.layers,d=!1,e=null,f=0;f<c.length;f++){var g=c[f],h=g.id;if(h===b){e=this.map.createLayer(g);d=!0;break}}if(!d)for(h in this.importLayers)if(h===b){e=this.importLayers[b];d=!0;break}d&&(a?(this.map.addLayer(b,e),this.attribution.onLayerShow({id:b})):(this.map.removeLayer(b),this.attribution.onLayerHide({id:b})));break;case "edit-layer":a?this.map.addLayer(netgis.Client.Layers.EDIT_LAYER,
|
netgis.Client.prototype.onLayerTreeItemChange=function(a){var b=a.detail.id;a=a.detail.checked;switch(b){default:for(var c=this.config.layers,d=!1,e=null,f=0;f<c.length;f++){var g=c[f],h=g.id;if(h===b){e=this.map.createLayer(g);d=!0;break}}if(!d)for(h in this.importLayers)if(h===b){e=this.importLayers[b];d=!0;break}d&&(a?(this.map.addLayer(b,e),this.attribution.onLayerShow({id:b})):(this.map.removeLayer(b),this.attribution.onLayerHide({id:b})));break;case "edit-layer":a?this.map.addLayer(netgis.Client.Layers.EDIT_LAYER,
|
||||||
this.map.editLayer):this.map.removeLayer(netgis.Client.Layers.EDIT_LAYER)}};netgis.Client.prototype.onToolboxToggle=function(a){this.toolboxPanel.toggle();this.toolboxPanel.visible()&&(this.layerPanel.hide(),this.parcelPanel.hide())};netgis.Client.prototype.onSearchPlaceToggle=function(a){this.searchPlace.toggle()};netgis.Client.prototype.onSearchPlaceSelect=function(a){a=a.detail;this.map.zoomExtent(a.minx,a.miny,a.maxx,a.maxy)};
|
this.map.editLayer):this.map.removeLayer(netgis.Client.Layers.EDIT_LAYER)}};netgis.Client.prototype.onToolboxToggle=function(a){this.toolboxPanel.toggle();this.toolboxPanel.visible()&&(this.layerPanel.hide(),this.parcelPanel.hide())};netgis.Client.prototype.onSearchPlaceToggle=function(a){this.searchPlace.toggle()};netgis.Client.prototype.onSearchPlaceSelect=function(a){a=a.detail;this.map.zoomExtent(a.minx,a.miny,a.maxx,a.maxy)};
|
||||||
netgis.Client.prototype.onSearchParcelToggle=function(a){this.parcelPanel.toggle();this.parcelPanel.visible()&&(this.layerPanel.hide(),this.toolboxPanel.hide())};netgis.Client.prototype.onControlsZoom=function(a){this.map.zoom(a.detail)};netgis.Client.prototype.onControlsZoomAll=function(a){this.map.zoomAll()};netgis.Client.prototype.onParcelsPanelToggle=function(a){this.searchParcel.reset()};
|
netgis.Client.prototype.onSearchParcelToggle=function(a){this.parcelPanel.toggle();this.parcelPanel.visible()&&(this.layerPanel.hide(),this.toolboxPanel.hide())};netgis.Client.prototype.onControlsZoom=function(a){this.map.zoom(a.detail)};netgis.Client.prototype.onControlsZoomAll=function(a){this.map.zoomAll()};netgis.Client.prototype.onParcelsPanelToggle=function(a){this.searchParcel.reset()};
|
||||||
netgis.Client.prototype.onParcelsReset=function(a){this.map.removeLayer(netgis.Client.Layers.PARCEL_DISTRICTS);this.map.removeLayer(netgis.Client.Layers.PARCEL_FIELDS);this.map.removeLayer(netgis.Client.Layers.PARCEL_FEATURES);if(this.parcelPanel.visible()){this.parcelsAdded=[];var b=this.config.searchParcel.districts_service;a=this.map.createLayer(b);var c=this.config.styles.parcel;this.map.setLayerStyleSimple(a,c.fill,c.stroke,c.width);this.map.addLayer(netgis.Client.Layers.PARCEL_DISTRICTS,a);
|
netgis.Client.prototype.onParcelsReset=function(a){this.map.removeLayer(netgis.Client.Layers.PARCEL_DISTRICTS);this.map.removeLayer(netgis.Client.Layers.PARCEL_FIELDS);this.map.removeLayer(netgis.Client.Layers.PARCEL_FEATURES);if(this.parcelPanel.visible()){this.parcelsAdded=[];var b=this.config.searchParcel.districts_service;a=this.map.createLayer(b);var c=this.config.styles.parcel;this.map.setLayerStyleSimple(a,c.fill,c.stroke,c.width);this.map.setLayerOrder(a,99999);this.map.addLayer(netgis.Client.Layers.PARCEL_DISTRICTS,
|
||||||
if(b.minZoom){var d=this;window.setTimeout(function(){d.map.zoomLevel(b.minZoom+1)},50)}this.setMode(netgis.Modes.PARCEL_SELECT)}else this.setMode(netgis.Modes.VIEW)};
|
a);if(b.minZoom){var d=this;window.setTimeout(function(){d.map.zoomLevel(b.minZoom+1)},50)}this.setMode(netgis.Modes.PARCEL_SELECT)}else this.setMode(netgis.Modes.VIEW)};
|
||||||
netgis.Client.prototype.onParcelsFieldsResponse=function(a){var b=a.detail;this.map.zoomGeoJSON(b.geojson);this.map.removeLayer(netgis.Client.Layers.PARCEL_DISTRICTS);a=this.config.styles.parcel;b=this.map.createLayerGeoJSON(b.geojson,!1);this.map.setLayerStyleSimple(b,a.fill,a.stroke,a.width);this.map.setLayerOrder(b,4E4);this.map.addLayer(netgis.Client.Layers.PARCEL_FIELDS,b)};
|
netgis.Client.prototype.onParcelsFieldsResponse=function(a){var b=a.detail;this.map.zoomGeoJSON(b.geojson);this.map.removeLayer(netgis.Client.Layers.PARCEL_DISTRICTS);a=this.config.styles.parcel;b=this.map.createLayerGeoJSON(b.geojson,!1);this.map.setLayerStyleSimple(b,a.fill,a.stroke,a.width);this.map.setLayerOrder(b,99999);this.map.addLayer(netgis.Client.Layers.PARCEL_FIELDS,b)};
|
||||||
netgis.Client.prototype.onParcelsResponse=function(a){a=this.map.createLayerWKT(a.detail.parcels);var b=this.config.styles.parcel;this.map.removeLayer(netgis.Client.Layers.PARCEL_DISTRICTS);this.map.removeLayer(netgis.Client.Layers.PARCEL_FIELDS);this.map.removeLayer(netgis.Client.Layers.PARCEL_FEATURES);this.map.setLayerStyleSimple(a,b.fill,b.stroke,b.width);this.map.addLayer(netgis.Client.Layers.PARCEL_FEATURES,a);this.map.zoomLayer(netgis.Client.Layers.PARCEL_FEATURES)};
|
netgis.Client.prototype.onParcelsResponse=function(a){a=this.map.createLayerWKT(a.detail.parcels);var b=this.config.styles.parcel;this.map.removeLayer(netgis.Client.Layers.PARCEL_DISTRICTS);this.map.removeLayer(netgis.Client.Layers.PARCEL_FIELDS);this.map.removeLayer(netgis.Client.Layers.PARCEL_FEATURES);this.map.setLayerStyleSimple(a,b.fill,b.stroke,b.width);this.map.setLayerOrder(a,99999);this.map.addLayer(netgis.Client.Layers.PARCEL_FEATURES,a);this.map.zoomLayer(netgis.Client.Layers.PARCEL_FEATURES)};
|
||||||
netgis.Client.prototype.onMapFeatureEnter=function(a){a=a.detail;switch(a.layer){case netgis.Client.Layers.PARCEL_DISTRICTS:a=a.properties.gemarkung;this.map.container.setAttribute("title",a);break;case netgis.Client.Layers.PARCEL_FIELDS:a=a.properties.flurname;this.map.container.setAttribute("title",a);break;case netgis.Client.Layers.PARCEL_FEATURES:a="Flur: "+a.properties.fln+" / Z\u00e4hler: "+a.properties.fsn_zae+" / Nenner: "+a.properties.fsn_nen,this.map.container.setAttribute("title",a+" (Klicken zum \u00dcbernehmen der Geometrie)")}};
|
netgis.Client.prototype.onMapFeatureEnter=function(a){a=a.detail;switch(a.layer){case netgis.Client.Layers.PARCEL_DISTRICTS:a=a.properties.gemarkung;this.map.container.setAttribute("title",a);break;case netgis.Client.Layers.PARCEL_FIELDS:a=a.properties.flurname;this.map.container.setAttribute("title",a);break;case netgis.Client.Layers.PARCEL_FEATURES:a="Flur: "+a.properties.fln+" / Z\u00e4hler: "+a.properties.fsn_zae+" / Nenner: "+a.properties.fsn_nen,this.editable&&(a+=" (Klicken zum \u00dcbernehmen der Geometrie)"),
|
||||||
netgis.Client.prototype.onMapFeatureClick=function(a){a=a.detail;switch(a.layer){default:console.info("Feature Click:",a);break;case netgis.Client.Layers.PARCEL_DISTRICTS:this.searchParcel.setDistrict(a.properties.gemarkung+" ("+a.properties.ldkreis+")",a.properties.gmkgnr);break;case netgis.Client.Layers.PARCEL_FIELDS:this.searchParcel.setFieldNumber(a.properties.flur);break;case netgis.Client.Layers.PARCEL_FEATURES:var b=a.properties.fsk;-1===this.parcelsAdded.indexOf(b)&&(this.map.addEditFeature(this.map.createFeatureJSON(a.properties)),
|
this.map.container.setAttribute("title",a)}};
|
||||||
this.map.updateSnapFeatures(),this.parcelsAdded.push(b))}};netgis.Client.prototype.onMapFeatureLeave=function(a){this.map.container.setAttribute("title","")};netgis.Client.prototype.onParcelsItemEnter=function(a){this.map.setFeatureHover(this.map.findFeature(netgis.Client.Layers.PARCEL_FEATURES,"fsk",a.detail.id),!0)};netgis.Client.prototype.onParcelsItemLeave=function(a){this.map.setFeatureHover(this.map.findFeature(netgis.Client.Layers.PARCEL_FEATURES,"fsk",a.detail.id),!1)};
|
netgis.Client.prototype.onMapFeatureClick=function(a){a=a.detail;switch(a.layer){default:console.info("Feature Click:",a);break;case netgis.Client.Layers.PARCEL_DISTRICTS:this.searchParcel.setDistrict(a.properties.gemarkung+" ("+a.properties.ldkreis+")",a.properties.gmkgnr);break;case netgis.Client.Layers.PARCEL_FIELDS:this.searchParcel.setFieldNumber(a.properties.flur);break;case netgis.Client.Layers.PARCEL_FEATURES:if(!0===this.editable){var b=a.properties.fsk;-1===this.parcelsAdded.indexOf(b)&&
|
||||||
netgis.Client.prototype.onParcelsItemClick=function(a){this.map.zoomFeature(this.map.findFeature(netgis.Client.Layers.PARCEL_FEATURES,"fsk",a.detail.id))};netgis.Client.prototype.onParcelsImportClick=function(a){a=a.detail;this.map.addEditFeature(this.map.createFeatureWKT(a.geom,{id:a.id}));this.map.updateSnapFeatures()};netgis.Client.prototype.onSetMode=function(a){this.setMode(a.detail)};
|
(this.map.addEditFeature(this.map.createFeatureJSON(a.properties)),this.map.updateSnapFeatures(),this.parcelsAdded.push(b))}}};netgis.Client.prototype.onMapFeatureLeave=function(a){this.map.container.setAttribute("title","")};netgis.Client.prototype.onParcelsItemEnter=function(a){this.map.setFeatureHover(this.map.findFeature(netgis.Client.Layers.PARCEL_FEATURES,"fsk",a.detail.id),!0)};
|
||||||
netgis.Client.prototype.onSnapToggle=function(a){(a=a.detail.target.checked)?(this.map.updateSnapFeatures(),this.map.setSnapOn()):this.map.setSnapOff();this.toolbox.setSnap(a)};netgis.Client.prototype.onTracingToggle=function(a){a.detail.target.checked?(this.map.updateSnapFeatures(),this.map.setSnapOn(),this.map.setTracingOn(),this.toolbox.setSnap(!0)):this.map.setTracingOff()};
|
netgis.Client.prototype.onParcelsItemLeave=function(a){this.map.setFeatureHover(this.map.findFeature(netgis.Client.Layers.PARCEL_FEATURES,"fsk",a.detail.id),!1)};netgis.Client.prototype.onParcelsItemClick=function(a){this.map.zoomFeature(this.map.findFeature(netgis.Client.Layers.PARCEL_FEATURES,"fsk",a.detail.id))};netgis.Client.prototype.onParcelsImportClick=function(a){a=a.detail;!1!==this.editable&&(this.map.addEditFeature(this.map.createFeatureWKT(a.geom,{id:a.id})),this.map.updateSnapFeatures())};
|
||||||
|
netgis.Client.prototype.onSetMode=function(a){this.setMode(a.detail)};netgis.Client.prototype.onSnapToggle=function(a){(a=a.detail.target.checked)?(this.map.updateSnapFeatures(),this.map.setSnapOn()):this.map.setSnapOff();this.toolbox.setSnap(a)};netgis.Client.prototype.onTracingToggle=function(a){a.detail.target.checked?(this.map.updateSnapFeatures(),this.map.setSnapOn(),this.map.setTracingOn(),this.toolbox.setSnap(!0)):this.map.setTracingOff()};
|
||||||
netgis.Client.prototype.onBufferToggle=function(a){if(a=a.detail.target.checked)this.map.onDrawBufferOn();else this.map.onDrawBufferOff();this.toolbox.setBuffer(a)};netgis.Client.prototype.onBufferRadiusChange=function(a){a=Number.parseFloat(a.detail.target.value);this.map.onDrawBufferRadiusChange(a);this.toolbox.setBufferRadius(a)};netgis.Client.prototype.onBufferSegmentsChange=function(a){a=Number.parseInt(a.detail.target.value);this.map.onDrawBufferSegmentsChange(a);this.toolbox.setBufferSegments(a)};
|
netgis.Client.prototype.onBufferToggle=function(a){if(a=a.detail.target.checked)this.map.onDrawBufferOn();else this.map.onDrawBufferOff();this.toolbox.setBuffer(a)};netgis.Client.prototype.onBufferRadiusChange=function(a){a=Number.parseFloat(a.detail.target.value);this.map.onDrawBufferRadiusChange(a);this.toolbox.setBufferRadius(a)};netgis.Client.prototype.onBufferSegmentsChange=function(a){a=Number.parseInt(a.detail.target.value);this.map.onDrawBufferSegmentsChange(a);this.toolbox.setBufferSegments(a)};
|
||||||
netgis.Client.prototype.onBufferFeatureChange=function(a){this.map.onBufferChange(a.detail)};netgis.Client.prototype.onBufferFeatureAccept=function(a){this.map.onBufferAccept()};netgis.Client.prototype.onImportShapefileShow=function(a){this.modal.onImportShapefileShow(a)};netgis.Client.prototype.onImportGeoJSONShow=function(a){this.modal.onImportGeoJSONShow(a)};netgis.Client.prototype.onImportGMLShow=function(a){this.modal.onImportGMLShow(a)};netgis.Client.prototype.onImportSpatialiteShow=function(a){this.modal.onImportSpatialiteShow(a)};
|
netgis.Client.prototype.onBufferFeatureChange=function(a){this.map.onBufferChange(a.detail)};netgis.Client.prototype.onBufferFeatureAccept=function(a){this.map.onBufferAccept()};netgis.Client.prototype.onImportShapefileShow=function(a){this.modal.onImportShapefileShow(a)};netgis.Client.prototype.onImportGeoJSONShow=function(a){this.modal.onImportGeoJSONShow(a)};netgis.Client.prototype.onImportGMLShow=function(a){this.modal.onImportGMLShow(a)};netgis.Client.prototype.onImportSpatialiteShow=function(a){this.modal.onImportSpatialiteShow(a)};
|
||||||
netgis.Client.prototype.onImportGeopackageShow=function(a){this.modal.onImportGeopackageShow(a)};netgis.Client.prototype.onExportPDFShow=function(a){this.modal.onExportPDFShow(a)};netgis.Client.prototype.onExportPNGShow=function(a){this.modal.onExportPNGShow(a)};netgis.Client.prototype.onExportJPEGShow=function(a){this.modal.onExportJPEGShow(a)};netgis.Client.prototype.onExportGIFShow=function(a){this.modal.onExportGIFShow(a)};netgis.Client.prototype.onExportPDF=function(a){this.map.onExportPDF(a)};
|
netgis.Client.prototype.onImportGeopackageShow=function(a){this.modal.onImportGeopackageShow(a)};netgis.Client.prototype.onExportPDFShow=function(a){this.modal.onExportPDFShow(a)};netgis.Client.prototype.onExportPNGShow=function(a){this.modal.onExportPNGShow(a)};netgis.Client.prototype.onExportJPEGShow=function(a){this.modal.onExportJPEGShow(a)};netgis.Client.prototype.onExportGIFShow=function(a){this.modal.onExportGIFShow(a)};netgis.Client.prototype.onExportPDF=function(a){this.map.onExportPDF(a)};
|
||||||
@@ -104,8 +105,8 @@ this.client.on(netgis.Events.PARCEL_SHOW_PREVIEW,this.onParcelShowPreview.bind(t
|
|||||||
this.onDrawBufferRadiusChange.bind(this));this.client.on(netgis.Events.DRAW_BUFFER_SEGMENTS_CHANGE,this.onDrawBufferSegmentsChange.bind(this))};
|
this.onDrawBufferRadiusChange.bind(this));this.client.on(netgis.Events.DRAW_BUFFER_SEGMENTS_CHANGE,this.onDrawBufferSegmentsChange.bind(this))};
|
||||||
netgis.MapOpenLayers.prototype.initMap=function(a){"undefined"!==typeof proj4&&(proj4.defs(a.projections),proj4.defs("urn:ogc:def:crs:OGC:1.3:CRS84",proj4.defs("EPSG:4326")),ol.proj.proj4.register(proj4));this.view=new ol.View({projection:a.map.projection,center:a.map.center,minZoom:a.map.minZoom,maxZoom:a.map.maxZoom,zoom:a.map.zoom});this.setPadding(0,0,0,0);this.map=new ol.Map({target:this.container,view:this.view,pixelRatio:1,moveTolerance:5,controls:[]});a.map.scalebar&&(this.scalebar=new ol.control.ScaleLine({bar:!0}),
|
netgis.MapOpenLayers.prototype.initMap=function(a){"undefined"!==typeof proj4&&(proj4.defs(a.projections),proj4.defs("urn:ogc:def:crs:OGC:1.3:CRS84",proj4.defs("EPSG:4326")),ol.proj.proj4.register(proj4));this.view=new ol.View({projection:a.map.projection,center:a.map.center,minZoom:a.map.minZoom,maxZoom:a.map.maxZoom,zoom:a.map.zoom});this.setPadding(0,0,0,0);this.map=new ol.Map({target:this.container,view:this.view,pixelRatio:1,moveTolerance:5,controls:[]});a.map.scalebar&&(this.scalebar=new ol.control.ScaleLine({bar:!0}),
|
||||||
this.map.addControl(this.scalebar));this.map.on("pointermove",this.onPointerMove.bind(this));this.map.on("click",this.onSingleClick.bind(this));this.map.on("movestart",this.onMoveStart.bind(this));this.map.on("moveend",this.onMoveEnd.bind(this));this.view.on("change:resolution",this.onChangeResolution.bind(this))};netgis.MapOpenLayers.prototype.initStyles=function(a){a=a.styles.select;this.hoverStyle=this.createStyle(a.fill,a.stroke,a.width);this.hoverStyle.setZIndex(1)};
|
this.map.addControl(this.scalebar));this.map.on("pointermove",this.onPointerMove.bind(this));this.map.on("click",this.onSingleClick.bind(this));this.map.on("movestart",this.onMoveStart.bind(this));this.map.on("moveend",this.onMoveEnd.bind(this));this.view.on("change:resolution",this.onChangeResolution.bind(this))};netgis.MapOpenLayers.prototype.initStyles=function(a){a=a.styles.select;this.hoverStyle=this.createStyle(a.fill,a.stroke,a.width);this.hoverStyle.setZIndex(1)};
|
||||||
netgis.MapOpenLayers.prototype.initDefaultLayers=function(){this.editLayer=new ol.layer.Vector({source:new ol.source.Vector({features:[]}),style:this.styleEdit.bind(this),zIndex:this.editLayerID});this.addLayer(netgis.Client.Layers.EDIT_LAYER,this.editLayer);this.previewLayer=new ol.layer.Vector({source:new ol.source.Vector({features:[]}),style:this.styleSketch.bind(this),zIndex:this.editLayerID+10});this.addLayer(netgis.Client.Layers.PREVIEW_LAYER,this.previewLayer);this.parcelLayer=new ol.layer.Vector({source:new ol.source.Vector({features:[]}),
|
netgis.MapOpenLayers.prototype.initDefaultLayers=function(){this.editLayer=new ol.layer.Vector({source:new ol.source.Vector({features:[]}),style:this.styleEdit.bind(this),zIndex:this.editLayerID});this.addLayer(netgis.Client.Layers.EDIT_LAYER,this.editLayer);this.previewLayer=new ol.layer.Vector({source:new ol.source.Vector({features:[]}),style:this.styleSketch.bind(this),zIndex:this.editLayerID+1E3});this.addLayer(netgis.Client.Layers.PREVIEW_LAYER,this.previewLayer);this.editEventsOn()};
|
||||||
style:this.styleParcel.bind(this),zIndex:this.editLayerID+20});this.map.addLayer(this.parcelLayer);this.editEventsOn()};netgis.MapOpenLayers.prototype.editEventsOn=function(){this.editLayer.getSource().on("addfeature",this.onEditLayerAdd.bind(this));this.editLayer.getSource().on("changefeature",this.onEditLayerChange.bind(this));this.editLayer.getSource().on("removefeature",this.onEditLayerRemove.bind(this))};netgis.MapOpenLayers.prototype.editEventsOff=function(){};
|
netgis.MapOpenLayers.prototype.editEventsOn=function(){this.editLayer.getSource().on("addfeature",this.onEditLayerAdd.bind(this));this.editLayer.getSource().on("changefeature",this.onEditLayerChange.bind(this));this.editLayer.getSource().on("removefeature",this.onEditLayerRemove.bind(this))};netgis.MapOpenLayers.prototype.editEventsOff=function(){};
|
||||||
netgis.MapOpenLayers.prototype.initInteractions=function(){this.interactions[netgis.Modes.VIEW]=[new ol.interaction.DragPan,new ol.interaction.MouseWheelZoom];this.interactions[netgis.Modes.PANNING]=this.interactions[netgis.Modes.VIEW];this.interactions[netgis.Modes.ZOOMING_IN]=this.interactions[netgis.Modes.VIEW];this.interactions[netgis.Modes.ZOOMING_OUT]=this.interactions[netgis.Modes.VIEW];this.interactions[netgis.Modes.DRAW_POINTS]=[new ol.interaction.Draw({type:"Point",source:this.editLayer.getSource(),
|
netgis.MapOpenLayers.prototype.initInteractions=function(){this.interactions[netgis.Modes.VIEW]=[new ol.interaction.DragPan,new ol.interaction.MouseWheelZoom];this.interactions[netgis.Modes.PANNING]=this.interactions[netgis.Modes.VIEW];this.interactions[netgis.Modes.ZOOMING_IN]=this.interactions[netgis.Modes.VIEW];this.interactions[netgis.Modes.ZOOMING_OUT]=this.interactions[netgis.Modes.VIEW];this.interactions[netgis.Modes.DRAW_POINTS]=[new ol.interaction.Draw({type:"Point",source:this.editLayer.getSource(),
|
||||||
style:this.styleSketch.bind(this)}),new ol.interaction.DragPan,new ol.interaction.MouseWheelZoom];this.interactions[netgis.Modes.DRAW_POINTS][0].on("drawend",this.onDrawPointsEnd.bind(this));this.interactions[netgis.Modes.DRAW_LINES]=[new ol.interaction.Draw({type:"LineString",source:this.editLayer.getSource(),style:this.styleSketch.bind(this)}),new ol.interaction.DragPan,new ol.interaction.MouseWheelZoom];this.interactions[netgis.Modes.DRAW_LINES][0].on("drawend",this.onDrawLinesEnd.bind(this));
|
style:this.styleSketch.bind(this)}),new ol.interaction.DragPan,new ol.interaction.MouseWheelZoom];this.interactions[netgis.Modes.DRAW_POINTS][0].on("drawend",this.onDrawPointsEnd.bind(this));this.interactions[netgis.Modes.DRAW_LINES]=[new ol.interaction.Draw({type:"LineString",source:this.editLayer.getSource(),style:this.styleSketch.bind(this)}),new ol.interaction.DragPan,new ol.interaction.MouseWheelZoom];this.interactions[netgis.Modes.DRAW_LINES][0].on("drawend",this.onDrawLinesEnd.bind(this));
|
||||||
this.interactions[netgis.Modes.DRAW_POLYGONS]=[new ol.interaction.Draw({type:"Polygon",source:this.editLayer.getSource(),style:this.styleSketch.bind(this)}),new ol.interaction.DragPan,new ol.interaction.MouseWheelZoom];this.interactions[netgis.Modes.CUT_FEATURE_BEGIN]=[new ol.interaction.DragPan,new ol.interaction.MouseWheelZoom];this.interactions[netgis.Modes.CUT_FEATURE_DRAW]=[new ol.interaction.Draw({type:"Polygon",style:this.styleSketch.bind(this)}),new ol.interaction.DragPan,new ol.interaction.MouseWheelZoom];
|
this.interactions[netgis.Modes.DRAW_POLYGONS]=[new ol.interaction.Draw({type:"Polygon",source:this.editLayer.getSource(),style:this.styleSketch.bind(this)}),new ol.interaction.DragPan,new ol.interaction.MouseWheelZoom];this.interactions[netgis.Modes.CUT_FEATURE_BEGIN]=[new ol.interaction.DragPan,new ol.interaction.MouseWheelZoom];this.interactions[netgis.Modes.CUT_FEATURE_DRAW]=[new ol.interaction.Draw({type:"Polygon",style:this.styleSketch.bind(this)}),new ol.interaction.DragPan,new ol.interaction.MouseWheelZoom];
|
||||||
@@ -134,7 +135,7 @@ netgis.MapOpenLayers.prototype.styleModify=function(a){var b=new ol.style.Style(
|
|||||||
geometry:this.getGeometryPoints(a)});a=a.getGeometry();a instanceof ol.geom.Polygon&&(a=a.getArea(),b.setText(new ol.style.Text({text:[netgis.util.formatArea(a,!0),"4mm sans-serif"],font:this.labelFont,fill:new ol.style.Fill({color:this.config.styles.modify.stroke}),backgroundFill:new ol.style.Fill({color:"rgba( 255, 255, 255, 0.5 )"}),padding:[2,4,2,4]})));return[b,c]};
|
geometry:this.getGeometryPoints(a)});a=a.getGeometry();a instanceof ol.geom.Polygon&&(a=a.getArea(),b.setText(new ol.style.Text({text:[netgis.util.formatArea(a,!0),"4mm sans-serif"],font:this.labelFont,fill:new ol.style.Fill({color:this.config.styles.modify.stroke}),backgroundFill:new ol.style.Fill({color:"rgba( 255, 255, 255, 0.5 )"}),padding:[2,4,2,4]})));return[b,c]};
|
||||||
netgis.MapOpenLayers.prototype.styleSketch=function(a){var b=a.getGeometry(),c=new ol.style.Style({image:new ol.style.Circle({radius:this.config.styles.sketch.pointRadius,fill:new ol.style.Fill({color:this.config.styles.sketch.stroke})}),fill:new ol.style.Fill({color:this.config.styles.sketch.fill}),stroke:new ol.style.Stroke({color:this.config.styles.sketch.stroke,width:this.config.styles.sketch.strokeWidth})});b instanceof ol.geom.Polygon&&(b=b.getArea(),c.setText(new ol.style.Text({text:[netgis.util.formatArea(b,
|
netgis.MapOpenLayers.prototype.styleSketch=function(a){var b=a.getGeometry(),c=new ol.style.Style({image:new ol.style.Circle({radius:this.config.styles.sketch.pointRadius,fill:new ol.style.Fill({color:this.config.styles.sketch.stroke})}),fill:new ol.style.Fill({color:this.config.styles.sketch.fill}),stroke:new ol.style.Stroke({color:this.config.styles.sketch.stroke,width:this.config.styles.sketch.strokeWidth})});b instanceof ol.geom.Polygon&&(b=b.getArea(),c.setText(new ol.style.Text({text:[netgis.util.formatArea(b,
|
||||||
!0),"4mm sans-serif"],font:this.labelFont,fill:new ol.style.Fill({color:this.config.styles.sketch.stroke}),backgroundFill:new ol.style.Fill({color:"rgba( 255, 255, 255, 0.5 )"}),padding:[2,4,2,4]})));a=new ol.style.Style({image:new ol.style.Circle({radius:this.config.styles.sketch.pointRadius,fill:new ol.style.Fill({color:this.config.styles.sketch.stroke})}),geometry:this.getGeometryPoints(a)});return[c,a]};
|
!0),"4mm sans-serif"],font:this.labelFont,fill:new ol.style.Fill({color:this.config.styles.sketch.stroke}),backgroundFill:new ol.style.Fill({color:"rgba( 255, 255, 255, 0.5 )"}),padding:[2,4,2,4]})));a=new ol.style.Style({image:new ol.style.Circle({radius:this.config.styles.sketch.pointRadius,fill:new ol.style.Fill({color:this.config.styles.sketch.stroke})}),geometry:this.getGeometryPoints(a)});return[c,a]};
|
||||||
netgis.MapOpenLayers.prototype.styleParcel=function(){return new ol.style.Style({fill:new ol.style.Fill({color:this.client.config.styles.parcel.fill}),stroke:new ol.style.Stroke({color:this.client.config.styles.parcel.stroke,width:this.client.config.styles.parcel.strokeWidth})})};netgis.MapOpenLayers.prototype.redrawVectorLayers=function(){this.map.getLayers().forEach(function(a,b,c){a instanceof ol.layer.Vector&&a.setStyle(a.getStyle())})};
|
netgis.MapOpenLayers.prototype.styleParcel=function(){return new ol.style.Style({fill:new ol.style.Fill({color:this.client.config.styles.parcel.fill}),stroke:new ol.style.Stroke({color:this.client.config.styles.parcel.stroke,width:this.client.config.styles.parcel.strokeWidth}),zIndex:99999})};netgis.MapOpenLayers.prototype.redrawVectorLayers=function(){this.map.getLayers().forEach(function(a,b,c){a instanceof ol.layer.Vector&&a.setStyle(a.getStyle())})};
|
||||||
netgis.MapOpenLayers.prototype.getGeometryPoints=function(a){var b=a.getGeometry();if(b instanceof ol.geom.LineString)return new ol.geom.MultiPoint(b.getCoordinates());if(b instanceof ol.geom.Polygon){a=[];b=b.getCoordinates();for(var c=0;c<b.length;c++)for(var d=b[c],e=0;e<d.length;e++)a.push(d[e]);return new ol.geom.MultiPoint(a)}if(b instanceof ol.geom.MultiPolygon){a=[];for(var f=b.getPolygons(),g=0;g<f.length;g++)for(b=f[g].getCoordinates(),c=0;c<b.length;c++)for(d=b[c],e=0;e<d.length;e++)a.push(d[e]);
|
netgis.MapOpenLayers.prototype.getGeometryPoints=function(a){var b=a.getGeometry();if(b instanceof ol.geom.LineString)return new ol.geom.MultiPoint(b.getCoordinates());if(b instanceof ol.geom.Polygon){a=[];b=b.getCoordinates();for(var c=0;c<b.length;c++)for(var d=b[c],e=0;e<d.length;e++)a.push(d[e]);return new ol.geom.MultiPoint(a)}if(b instanceof ol.geom.MultiPolygon){a=[];for(var f=b.getPolygons(),g=0;g<f.length;g++)for(b=f[g].getCoordinates(),c=0;c<b.length;c++)for(d=b[c],e=0;e<d.length;e++)a.push(d[e]);
|
||||||
return new ol.geom.MultiPoint(a)}if(b instanceof ol.geom.MultiLineString){a=[];f=b.getPolygons();for(g=0;g<f.length;g++)for(b=f[g].getCoordinates(),c=0;c<b.length;c++)for(d=b[c],e=0;e<d.length;e++)a.push(d[e]);return new ol.geom.MultiPoint(a)}return b};netgis.MapOpenLayers.prototype.getActiveVectorLayers=function(){for(var a=[],b=this.map.getLayers().getArray(),c=this.layers,d=0;d<c.length;d++){var e=c[d];e instanceof ol.layer.Vector&&-1<b.indexOf(e)&&a.push(e)}return a};
|
return new ol.geom.MultiPoint(a)}if(b instanceof ol.geom.MultiLineString){a=[];f=b.getPolygons();for(g=0;g<f.length;g++)for(b=f[g].getCoordinates(),c=0;c<b.length;c++)for(d=b[c],e=0;e<d.length;e++)a.push(d[e]);return new ol.geom.MultiPoint(a)}return b};netgis.MapOpenLayers.prototype.getActiveVectorLayers=function(){for(var a=[],b=this.map.getLayers().getArray(),c=this.layers,d=0;d<c.length;d++){var e=c[d];e instanceof ol.layer.Vector&&-1<b.indexOf(e)&&a.push(e)}return a};
|
||||||
netgis.MapOpenLayers.prototype.setMode=function(a){switch(this.mode){case netgis.Modes.BUFFER_FEATURE_EDIT:this.onBufferCancel(null);break;case netgis.Modes.DRAW_POINTS:case netgis.Modes.DRAW_LINES:var b=this.drawBufferOn;this.onDrawBufferOff(null);this.drawBufferOn=b;break;case netgis.Modes.MODIFY_FEATURES:this.editLayer.setStyle(this.styleEdit.bind(this))}this.container.classList.remove("netgis-cursor-draw");this.container.classList.remove("netgis-clickable");switch(a){case netgis.Modes.DRAW_POINTS:this.container.classList.add("netgis-cursor-draw");
|
netgis.MapOpenLayers.prototype.setMode=function(a){switch(this.mode){case netgis.Modes.BUFFER_FEATURE_EDIT:this.onBufferCancel(null);break;case netgis.Modes.DRAW_POINTS:case netgis.Modes.DRAW_LINES:var b=this.drawBufferOn;this.onDrawBufferOff(null);this.drawBufferOn=b;break;case netgis.Modes.MODIFY_FEATURES:this.editLayer.setStyle(this.styleEdit.bind(this))}this.container.classList.remove("netgis-cursor-draw");this.container.classList.remove("netgis-clickable");switch(a){case netgis.Modes.DRAW_POINTS:this.container.classList.add("netgis-cursor-draw");
|
||||||
@@ -153,9 +154,10 @@ netgis.MapOpenLayers.prototype.onAddServiceWMS=function(a){var b=this.createLaye
|
|||||||
netgis.MapOpenLayers.prototype.onSetExtent=function(a){var b=ol.proj.fromLonLat([a.minx,a.miny],this.client.config.map.projection);a=ol.proj.fromLonLat([a.maxx,a.maxy],this.client.config.map.projection);this.view.fit([b[0],b[1],a[0],a[1]])};netgis.MapOpenLayers.prototype.onChangeZoom=function(a){this.view.animate({zoom:this.view.getZoom()+a,duration:200})};netgis.MapOpenLayers.prototype.onZoomWKT=function(a){a=(new ol.format.WKT).readGeometry(a);this.view.fit(a,{duration:300,padding:[40,40,40,40]})};
|
netgis.MapOpenLayers.prototype.onSetExtent=function(a){var b=ol.proj.fromLonLat([a.minx,a.miny],this.client.config.map.projection);a=ol.proj.fromLonLat([a.maxx,a.maxy],this.client.config.map.projection);this.view.fit([b[0],b[1],a[0],a[1]])};netgis.MapOpenLayers.prototype.onChangeZoom=function(a){this.view.animate({zoom:this.view.getZoom()+a,duration:200})};netgis.MapOpenLayers.prototype.onZoomWKT=function(a){a=(new ol.format.WKT).readGeometry(a);this.view.fit(a,{duration:300,padding:[40,40,40,40]})};
|
||||||
netgis.MapOpenLayers.prototype.onPointerMove=function(a){var b=a.pixel;a=a.coordinate;var c=null,d=null;this.map.forEachFeatureAtPixel(b,function(a,b){if(b){if(b.get("id")&&netgis.util.isString(b.get("id"))&&-1!==b.get("id").search("import-"))return!1;c=a;d=b;return!0}});switch(this.mode){default:return!0;case netgis.Modes.PARCEL_SELECT:case netgis.Modes.DELETE_FEATURES:case netgis.Modes.CUT_FEATURE_BEGIN:case netgis.Modes.BUFFER_FEATURE_BEGIN:break;case netgis.Modes.DRAW_POINTS:case netgis.Modes.DRAW_LINES:return this.updateDrawBufferPreview(),
|
netgis.MapOpenLayers.prototype.onPointerMove=function(a){var b=a.pixel;a=a.coordinate;var c=null,d=null;this.map.forEachFeatureAtPixel(b,function(a,b){if(b){if(b.get("id")&&netgis.util.isString(b.get("id"))&&-1!==b.get("id").search("import-"))return!1;c=a;d=b;return!0}});switch(this.mode){default:return!0;case netgis.Modes.PARCEL_SELECT:case netgis.Modes.DELETE_FEATURES:case netgis.Modes.CUT_FEATURE_BEGIN:case netgis.Modes.BUFFER_FEATURE_BEGIN:break;case netgis.Modes.DRAW_POINTS:case netgis.Modes.DRAW_LINES:return this.updateDrawBufferPreview(),
|
||||||
!0}c!==this.hoverFeature&&(this.hoverFeature&&this.featureLeave(this.hoverFeature,this.hoverLayer,b,a),c&&this.featureEnter(c,d,b,a),this.redrawVectorLayers(),this.hoverFeature=c,this.hoverLayer=d);c&&this.featureHover(c,d,b,a)};netgis.MapOpenLayers.prototype.onPointerLeave=function(a){this.hoverFeature&&(this.featureLeave(this.hoverFeature,this.hoverLayer,[a.offsetX,a.offsetY],null),this.hoverLayer=this.hoverFeature=null)};
|
!0}c!==this.hoverFeature&&(this.hoverFeature&&this.featureLeave(this.hoverFeature,this.hoverLayer,b,a),c&&this.featureEnter(c,d,b,a),this.redrawVectorLayers(),this.hoverFeature=c,this.hoverLayer=d);c&&this.featureHover(c,d,b,a)};netgis.MapOpenLayers.prototype.onPointerLeave=function(a){this.hoverFeature&&(this.featureLeave(this.hoverFeature,this.hoverLayer,[a.offsetX,a.offsetY],null),this.hoverLayer=this.hoverFeature=null)};
|
||||||
netgis.MapOpenLayers.prototype.featureEnter=function(a,b,c,d){b&&(this.container.classList.add("netgis-clickable"),b.get("id")!==netgis.Client.Layers.EDIT_LAYER&&-1===b.get("id").search("import-")&&a.setStyle(this.hoverStyle),netgis.util.invoke(this.container,netgis.Events.MAP_FEATURE_ENTER,{pixel:c,coords:d,layer:b.get("id"),properties:a.getProperties()}))};netgis.MapOpenLayers.prototype.featureHover=function(a,b,c,d){};
|
netgis.MapOpenLayers.prototype.featureEnter=function(a,b,c,d){if(b){this.container.classList.add("netgis-clickable");var e=!1;b.get("id")===netgis.Client.Layers.EDIT_LAYER&&(e=!0);b.get("id")===netgis.Client.Layers.PARCEL_DISTRICTS&&(e=!0);b.get("id")===netgis.Client.Layers.PARCEL_FIELDS&&(e=!0);b.get("id")===netgis.Client.Layers.PARCEL_FEATURES&&(e=!0);e&&a.setStyle(this.hoverStyle);netgis.util.invoke(this.container,netgis.Events.MAP_FEATURE_ENTER,{pixel:c,coords:d,layer:b.get("id"),properties:a.getProperties()})}};
|
||||||
netgis.MapOpenLayers.prototype.featureLeave=function(a,b,c,d){b&&(this.container.classList.remove("netgis-clickable"),b.get("id")!==netgis.Client.Layers.EDIT_LAYER&&a.setStyle(null),netgis.util.invoke(this.container,netgis.Events.MAP_FEATURE_LEAVE,{pixel:c,coords:d,layer:b.get("id"),properties:a.getProperties()}))};netgis.MapOpenLayers.prototype.findFeature=function(a,b,c){if(a=this.activeLayers[a]){a=a.getSource().getFeatures();for(var d=null,e=0;e<a.length;e++){var f=a[e];if(f.get(b)===c){d=f;break}}return d}};
|
netgis.MapOpenLayers.prototype.featureHover=function(a,b,c,d){};netgis.MapOpenLayers.prototype.featureLeave=function(a,b,c,d){b&&(this.container.classList.remove("netgis-clickable"),b.get("id")!==netgis.Client.Layers.EDIT_LAYER&&a.setStyle(null),netgis.util.invoke(this.container,netgis.Events.MAP_FEATURE_LEAVE,{pixel:c,coords:d,layer:b.get("id"),properties:a.getProperties()}))};
|
||||||
netgis.MapOpenLayers.prototype.setFeatureHover=function(a,b){a.setStyle(b?this.hoverStyle:null)};netgis.MapOpenLayers.prototype.onPointerMove_01=function(a){a=a.pixel;var b=this.hoverFeature,c=this;switch(this.mode){case netgis.Modes.DRAW_POINTS:case netgis.Modes.DRAW_LINES:this.updateDrawBufferPreview()}b=null;this.map.forEachFeatureAtPixel(a,function(a,e){e===c.editLayer&&(b=a);return!0});b!==this.hoverFeature&&this.redrawVectorLayers();this.hoverFeature=b};
|
netgis.MapOpenLayers.prototype.findFeature=function(a,b,c){if(a=this.activeLayers[a]){a=a.getSource().getFeatures();for(var d=null,e=0;e<a.length;e++){var f=a[e];if(f.get(b)===c){d=f;break}}return d}};netgis.MapOpenLayers.prototype.setFeatureHover=function(a,b){a.setStyle(b?this.hoverStyle:null)};
|
||||||
|
netgis.MapOpenLayers.prototype.onPointerMove_01=function(a){a=a.pixel;var b=this.hoverFeature,c=this;switch(this.mode){case netgis.Modes.DRAW_POINTS:case netgis.Modes.DRAW_LINES:this.updateDrawBufferPreview()}b=null;this.map.forEachFeatureAtPixel(a,function(a,e){e===c.editLayer&&(b=a);return!0});b!==this.hoverFeature&&this.redrawVectorLayers();this.hoverFeature=b};
|
||||||
netgis.MapOpenLayers.prototype.onSingleClick=function(a){switch(this.mode){default:this.hoverFeature&&this.hoverLayer&&(a={pixel:a.pixel,coords:a.coordinate,layer:this.hoverLayer.get("id"),id:this.hoverFeature.getId(),properties:this.hoverFeature.getProperties()},netgis.util.invoke(this.container,netgis.Events.MAP_FEATURE_CLICK,a));break;case netgis.Modes.DELETE_FEATURES:this.hoverFeature&&(this.editLayer.getSource().removeFeature(this.hoverFeature),this.featureLeave(this.hoverFeature,this.editLayer),
|
netgis.MapOpenLayers.prototype.onSingleClick=function(a){switch(this.mode){default:this.hoverFeature&&this.hoverLayer&&(a={pixel:a.pixel,coords:a.coordinate,layer:this.hoverLayer.get("id"),id:this.hoverFeature.getId(),properties:this.hoverFeature.getProperties()},netgis.util.invoke(this.container,netgis.Events.MAP_FEATURE_CLICK,a));break;case netgis.Modes.DELETE_FEATURES:this.hoverFeature&&(this.editLayer.getSource().removeFeature(this.hoverFeature),this.featureLeave(this.hoverFeature,this.editLayer),
|
||||||
this.hoverFeature=null,netgis.util.invoke(this.container,netgis.Events.SET_MODE,netgis.Modes.VIEW));break;case netgis.Modes.CUT_FEATURE_BEGIN:this.hoverFeature&&(this.selected=this.hoverFeature,netgis.util.invoke(this.container,netgis.Events.SET_MODE,netgis.Modes.CUT_FEATURE_DRAW));break;case netgis.Modes.BUFFER_FEATURE_BEGIN:this.hoverFeature&&(this.selected=this.hoverFeature,netgis.util.invoke(this.container,netgis.Events.SET_MODE,netgis.Modes.BUFFER_FEATURE_EDIT))}};
|
this.hoverFeature=null,netgis.util.invoke(this.container,netgis.Events.SET_MODE,netgis.Modes.VIEW));break;case netgis.Modes.CUT_FEATURE_BEGIN:this.hoverFeature&&(this.selected=this.hoverFeature,netgis.util.invoke(this.container,netgis.Events.SET_MODE,netgis.Modes.CUT_FEATURE_DRAW));break;case netgis.Modes.BUFFER_FEATURE_BEGIN:this.hoverFeature&&(this.selected=this.hoverFeature,netgis.util.invoke(this.container,netgis.Events.SET_MODE,netgis.Modes.BUFFER_FEATURE_EDIT))}};
|
||||||
netgis.MapOpenLayers.prototype.onMoveStart=function(a){};netgis.MapOpenLayers.prototype.onMoveEnd=function(a){};netgis.MapOpenLayers.prototype.onChangeResolution=function(a){};
|
netgis.MapOpenLayers.prototype.onMoveStart=function(a){};netgis.MapOpenLayers.prototype.onMoveEnd=function(a){};netgis.MapOpenLayers.prototype.onChangeResolution=function(a){};
|
||||||
@@ -194,8 +196,8 @@ function(){var n=document.createElement("canvas");n.width=b;n.height=c;var p=n.g
|
|||||||
t.setFillColor(255,255,255);t.rect(x,r+u-11,80,11,"F");t.setFontSize(8);t.text("Datum: "+netgis.util.getTimeStamp(),x+2,r+u-2-4);t.text("Quelle: "+window.location.href,x+2,r+u-2);n=t.output("bloburl",{filename:k.export.defaultFilename+".pdf"});window.open(n,"_blank");break;case "jpeg":window.navigator.msSaveBlob?window.navigator.msSaveBlob(n.msToBlob(),k.export.defaultFilename+".jpg"):(q.setAttribute("download",k.export.defaultFilename+".jpg"),q.setAttribute("href",n.toDataURL("image/jpeg",1)),q.click());
|
t.setFillColor(255,255,255);t.rect(x,r+u-11,80,11,"F");t.setFontSize(8);t.text("Datum: "+netgis.util.getTimeStamp(),x+2,r+u-2-4);t.text("Quelle: "+window.location.href,x+2,r+u-2);n=t.output("bloburl",{filename:k.export.defaultFilename+".pdf"});window.open(n,"_blank");break;case "jpeg":window.navigator.msSaveBlob?window.navigator.msSaveBlob(n.msToBlob(),k.export.defaultFilename+".jpg"):(q.setAttribute("download",k.export.defaultFilename+".jpg"),q.setAttribute("href",n.toDataURL("image/jpeg",1)),q.click());
|
||||||
break;case "png":window.navigator.msSaveBlob?window.navigator.msSaveBlob(n.msToBlob(),k.export.defaultFilename+".png"):(q.setAttribute("download",k.export.defaultFilename+".png"),q.setAttribute("href",n.toDataURL("image/png",1)),q.click());break;case "gif":q.setAttribute("download",k.export.defaultFilename+".gif"),v=new GIF({workerScript:k.export.gifWebWorker,quality:1}),v.addFrame(n),v.on("finished",function(a){q.setAttribute("href",window.URL.createObjectURL(a));q.click()}),v.render()}h.setTarget(g);
|
break;case "png":window.navigator.msSaveBlob?window.navigator.msSaveBlob(n.msToBlob(),k.export.defaultFilename+".png"):(q.setAttribute("download",k.export.defaultFilename+".png"),q.setAttribute("href",n.toDataURL("image/png",1)),q.click());break;case "gif":q.setAttribute("download",k.export.defaultFilename+".gif"),v=new GIF({workerScript:k.export.gifWebWorker,quality:1}),v.addFrame(n),v.on("finished",function(a){q.setAttribute("href",window.URL.createObjectURL(a));q.click()}),v.render()}h.setTarget(g);
|
||||||
g.removeChild(m);netgis.util.invoke(f.container,netgis.Events.EXPORT_END,null)});h.renderSync()};l.src=k.export.logo};netgis.MapOpenLayers.prototype.splitMultiPolygons=function(a){a=a.getSource();for(var b=a.getFeatures(),c=[],d=[],e=0;e<b.length;e++){var f=b[e],g=f.getGeometry();if(g instanceof ol.geom.MultiPolygon){g=g.getPolygons();for(var h=0;h<g.length;h++){var k=new ol.Feature({geometry:g[h]});d.push(k)}c.push(f)}}for(e=0;e<c.length;e++)a.removeFeature(c[e]);a.addFeatures(d)};netgis=netgis||{};netgis.Menu=function(){this.root=this.client=null;this.sections=[]};
|
g.removeChild(m);netgis.util.invoke(f.container,netgis.Events.EXPORT_END,null)});h.renderSync()};l.src=k.export.logo};netgis.MapOpenLayers.prototype.splitMultiPolygons=function(a){a=a.getSource();for(var b=a.getFeatures(),c=[],d=[],e=0;e<b.length;e++){var f=b[e],g=f.getGeometry();if(g instanceof ol.geom.MultiPolygon){g=g.getPolygons();for(var h=0;h<g.length;h++){var k=new ol.Feature({geometry:g[h]});d.push(k)}c.push(f)}}for(e=0;e<c.length;e++)a.removeFeature(c[e]);a.addFeatures(d)};netgis=netgis||{};netgis.Menu=function(){this.root=this.client=null;this.sections=[]};
|
||||||
netgis.Menu.prototype.load=function(){this.root=document.createElement("header");this.root.className="netgis-menu netgis-color-a netgis-shadow";var a=document.createElement("div");this.root.appendChild(a);var b=this.createButton('<i class="fab fa-buffer"></i><span>Inhalte</span>',!0);b.addEventListener("click",this.onToggleClick.bind(this));a.appendChild(b);b=this.createButton('<i class="fas fa-tools"></i><span>Werkzeuge</span>',!0);b.addEventListener("click",this.onToolboxClick.bind(this));a.appendChild(b);
|
netgis.Menu.prototype.load=function(){this.root=document.createElement("header");this.root.className="netgis-menu netgis-color-a netgis-shadow";var a=document.createElement("div");this.root.appendChild(a);var b=this.createButton('<i class="fab fa-buffer"></i><span>Inhalte</span>',!0);b.addEventListener("click",this.onToggleClick.bind(this));a.appendChild(b);!0===this.client.editable&&(b=this.createButton('<i class="fas fa-tools"></i><span>Werkzeuge</span>',!0),b.addEventListener("click",this.onToolboxClick.bind(this)),
|
||||||
b=this.createButton('<i class="fas fa-vector-square"></i><span>Flurst\u00fccke</span>',!0);b.addEventListener("click",this.onSearchParcelClick.bind(this));a.appendChild(b);b=this.createButton('<i class="fas fa-search"></i><span>Suche</span>',!0);b.addEventListener("click",this.onSearchPlaceClick.bind(this));a.appendChild(b);this.client.editable&&(a=this.createMenu('<i class="fas fa-caret-down"></i>Zeichnen').getElementsByTagName("ul")[0],a.appendChild(this.createMenuItem('<i class="fas fa-map-marker-alt"></i>Punkte',
|
a.appendChild(b));b=this.createButton('<i class="fas fa-vector-square"></i><span>Flurst\u00fccke</span>',!0);b.addEventListener("click",this.onSearchParcelClick.bind(this));a.appendChild(b);b=this.createButton('<i class="fas fa-search"></i><span>Suche</span>',!0);b.addEventListener("click",this.onSearchPlaceClick.bind(this));a.appendChild(b);this.client.editable&&(a=this.createMenu('<i class="fas fa-caret-down"></i>Zeichnen').getElementsByTagName("ul")[0],a.appendChild(this.createMenuItem('<i class="fas fa-map-marker-alt"></i>Punkte',
|
||||||
this.onDrawPointClick.bind(this))),a.appendChild(this.createMenuItem('<i class="fas fa-minus"></i>Linien',this.onDrawLineClick.bind(this))),a.appendChild(this.createMenuItem('<i class="fas fa-vector-square"></i>Polygone',this.onDrawPolygonClick.bind(this))),a=this.createMenu('<i class="fas fa-caret-down"></i>Bearbeiten').getElementsByTagName("ul")[0],a.appendChild(this.createMenuItem('<i class="fas fa-cut"></i>Ausschneiden',this.onCutFeatureClick.bind(this))),a.appendChild(this.createMenuItem('<i class="fas fa-arrows-alt"></i>Verschieben',
|
this.onDrawPointClick.bind(this))),a.appendChild(this.createMenuItem('<i class="fas fa-minus"></i>Linien',this.onDrawLineClick.bind(this))),a.appendChild(this.createMenuItem('<i class="fas fa-vector-square"></i>Polygone',this.onDrawPolygonClick.bind(this))),a=this.createMenu('<i class="fas fa-caret-down"></i>Bearbeiten').getElementsByTagName("ul")[0],a.appendChild(this.createMenuItem('<i class="fas fa-cut"></i>Ausschneiden',this.onCutFeatureClick.bind(this))),a.appendChild(this.createMenuItem('<i class="fas fa-arrows-alt"></i>Verschieben',
|
||||||
this.onModifyFeaturesClick.bind(this))),a.appendChild(this.createMenuItem('<i class="fas fa-eraser"></i>L\u00f6schen',this.onDeleteFeaturesClick.bind(this))),a.appendChild(this.createMenuItem('<i class="far fa-dot-circle"></i>Puffern',this.onBufferFeatureClick.bind(this))),a=this.createMenu('<i class="fas fa-caret-down"></i>Import').getElementsByTagName("ul")[0],a.appendChild(this.createMenuItem('<i class="fas fa-file"></i>GeoJSON',this.onImportGeoJSONClick.bind(this))),a.appendChild(this.createMenuItem('<i class="fas fa-file"></i>GML',
|
this.onModifyFeaturesClick.bind(this))),a.appendChild(this.createMenuItem('<i class="fas fa-eraser"></i>L\u00f6schen',this.onDeleteFeaturesClick.bind(this))),a.appendChild(this.createMenuItem('<i class="far fa-dot-circle"></i>Puffern',this.onBufferFeatureClick.bind(this))),a=this.createMenu('<i class="fas fa-caret-down"></i>Import').getElementsByTagName("ul")[0],a.appendChild(this.createMenuItem('<i class="fas fa-file"></i>GeoJSON',this.onImportGeoJSONClick.bind(this))),a.appendChild(this.createMenuItem('<i class="fas fa-file"></i>GML',
|
||||||
this.onImportGMLClick.bind(this))),a.appendChild(this.createMenuItem('<i class="fas fa-file"></i>Shapefile',this.onImportShapefileClick.bind(this))),a.appendChild(this.createMenuItem('<i class="fas fa-file"></i>Spatialite',this.onImportSpatialiteClick.bind(this))),a.appendChild(this.createMenuItem('<i class="fas fa-file"></i>GeoPackage',this.onImportGeopackageClick.bind(this))),a=this.createMenu('<i class="fas fa-caret-down"></i>Export').getElementsByTagName("ul")[0],a.appendChild(this.createMenuItem('<i class="fas fa-file"></i>PDF',
|
this.onImportGMLClick.bind(this))),a.appendChild(this.createMenuItem('<i class="fas fa-file"></i>Shapefile',this.onImportShapefileClick.bind(this))),a.appendChild(this.createMenuItem('<i class="fas fa-file"></i>Spatialite',this.onImportSpatialiteClick.bind(this))),a.appendChild(this.createMenuItem('<i class="fas fa-file"></i>GeoPackage',this.onImportGeopackageClick.bind(this))),a=this.createMenu('<i class="fas fa-caret-down"></i>Export').getElementsByTagName("ul")[0],a.appendChild(this.createMenuItem('<i class="fas fa-file"></i>PDF',
|
||||||
@@ -218,7 +220,7 @@ l){k=e;m=!0;break}m||(e=c.folders.length,c.folders.push({title:h,parent:k,path:l
|
|||||||
l[0];c.layers.push({folder:g,type:netgis.LayerTypes.XYZ,url:k.href,title:f.title,attribution:f.rights,active:f.active});break;case "http://www.opengis.net/spec/owc-geojson/1.0/req/osm":k=l[0],c.layers.push({folder:g,type:netgis.LayerTypes.XYZ,url:k.href,title:f.title,attribution:f.rights,active:f.active})}}b.invoke(netgis.Events.CONTEXT_UPDATE,c)}}}();netgis=netgis||{};netgis.Panel=function(a){this.initElements(a);this.initEvents()};netgis.Panel.prototype.initElements=function(a){var b=document.createElement("section");b.className="netgis-panel netgis-resize-right netgis-color-e netgis-shadow";this.addHeader(b,a,this.onHeaderClick.bind(this));this.container=b};netgis.Panel.prototype.initEvents=function(){this.resizeObserver=(new ResizeObserver(this.onResize.bind(this))).observe(this.container)};netgis.Panel.prototype.attach=function(a){a.appendChild(this.container)};
|
l[0];c.layers.push({folder:g,type:netgis.LayerTypes.XYZ,url:k.href,title:f.title,attribution:f.rights,active:f.active});break;case "http://www.opengis.net/spec/owc-geojson/1.0/req/osm":k=l[0],c.layers.push({folder:g,type:netgis.LayerTypes.XYZ,url:k.href,title:f.title,attribution:f.rights,active:f.active})}}b.invoke(netgis.Events.CONTEXT_UPDATE,c)}}}();netgis=netgis||{};netgis.Panel=function(a){this.initElements(a);this.initEvents()};netgis.Panel.prototype.initElements=function(a){var b=document.createElement("section");b.className="netgis-panel netgis-resize-right netgis-color-e netgis-shadow";this.addHeader(b,a,this.onHeaderClick.bind(this));this.container=b};netgis.Panel.prototype.initEvents=function(){this.resizeObserver=(new ResizeObserver(this.onResize.bind(this))).observe(this.container)};netgis.Panel.prototype.attach=function(a){a.appendChild(this.container)};
|
||||||
netgis.Panel.prototype.addHeader=function(a,b,c){var d=document.createElement("button");d.className="netgis-button netgis-clip-text netgis-color-c";d.innerHTML="<span>"+b+"</span><i class='netgis-icon fas fa-times'></i>";d.setAttribute("type","button");c&&(d.onclick=c);a&&a.appendChild(d);return d};netgis.Panel.prototype.show=function(){this.container.classList.add("netgis-show");netgis.util.invoke(this.container,netgis.Events.PANEL_TOGGLE,{panel:this,visible:!0})};
|
netgis.Panel.prototype.addHeader=function(a,b,c){var d=document.createElement("button");d.className="netgis-button netgis-clip-text netgis-color-c";d.innerHTML="<span>"+b+"</span><i class='netgis-icon fas fa-times'></i>";d.setAttribute("type","button");c&&(d.onclick=c);a&&a.appendChild(d);return d};netgis.Panel.prototype.show=function(){this.container.classList.add("netgis-show");netgis.util.invoke(this.container,netgis.Events.PANEL_TOGGLE,{panel:this,visible:!0})};
|
||||||
netgis.Panel.prototype.hide=function(){this.container.classList.remove("netgis-show");netgis.util.invoke(this.container,netgis.Events.PANEL_TOGGLE,{panel:this,visible:!1})};netgis.Panel.prototype.toggle=function(){this.container.classList.toggle("netgis-show");netgis.util.invoke(this.container,netgis.Events.PANEL_TOGGLE,{panel:this,visible:this.container.classList.contains("netgis-show")})};netgis.Panel.prototype.visible=function(){return this.container.classList.contains("netgis-show")};
|
netgis.Panel.prototype.hide=function(){this.container.classList.remove("netgis-show");netgis.util.invoke(this.container,netgis.Events.PANEL_TOGGLE,{panel:this,visible:!1})};netgis.Panel.prototype.toggle=function(){this.container.classList.toggle("netgis-show");netgis.util.invoke(this.container,netgis.Events.PANEL_TOGGLE,{panel:this,visible:this.container.classList.contains("netgis-show")})};netgis.Panel.prototype.visible=function(){return this.container.classList.contains("netgis-show")};
|
||||||
netgis.Panel.prototype.width=function(){return this.container.getBoundingClientRect().width};netgis.Panel.prototype.onHeaderClick=function(a){this.hide()};netgis.Panel.prototype.onResize=function(a){this.container.classList.contains("netgis-show")&&(a=this.container.getBoundingClientRect(),netgis.util.invoke(this.container,netgis.Events.PANEL_RESIZE,{width:a.width}))};netgis=netgis||{};netgis.SearchParcel=function(a){this.config=a;this.initElements();this.initEvents()};netgis.SearchParcel.Events=Object.freeze({TOGGLE:"search-parcel-toggle"});
|
netgis.Panel.prototype.width=function(){return this.container.getBoundingClientRect().width};netgis.Panel.prototype.onHeaderClick=function(a){this.hide()};netgis.Panel.prototype.onResize=function(a){this.container.classList.contains("netgis-show")&&(a=this.container.getBoundingClientRect(),netgis.util.invoke(this.container,netgis.Events.PANEL_RESIZE,{width:a.width}))};netgis=netgis||{};netgis.SearchParcel=function(a,b){this.client=b;this.config=a;this.initElements();this.initEvents()};netgis.SearchParcel.Events=Object.freeze({TOGGLE:"search-parcel-toggle"});
|
||||||
netgis.SearchParcel.prototype.initElements=function(){this.container=document.createElement("section");this.container.className="netgis-search-parcel";var a=document.createElement("section");this.top=a;this.container.appendChild(a);var b=this.createInput("Gemarkungsname:");b.style.position="relative";a.appendChild(b);this.nameInput=b.children[0];this.nameInput.setAttribute("title","ENTER: Ausw\u00e4hlen, ESCAPE: Zur\u00fccksetzen");this.nameInput.addEventListener("keyup",this.onInputNameKey.bind(this));
|
netgis.SearchParcel.prototype.initElements=function(){this.container=document.createElement("section");this.container.className="netgis-search-parcel";var a=document.createElement("section");this.top=a;this.container.appendChild(a);var b=this.createInput("Gemarkungsname:");b.style.position="relative";a.appendChild(b);this.nameInput=b.children[0];this.nameInput.setAttribute("title","ENTER: Ausw\u00e4hlen, ESCAPE: Zur\u00fccksetzen");this.nameInput.addEventListener("keyup",this.onInputNameKey.bind(this));
|
||||||
this.nameLoader=document.createElement("div");this.nameLoader.className="netgis-loader netgis-text-primary netgis-hide";this.nameLoader.innerHTML="<i class='fas fa-spinner'></i>";b.appendChild(this.nameLoader);this.nameList=document.createElement("ul");a.appendChild(this.nameList);b=this.createInput("Gemarkungsnummer:");this.districtInput=b.children[0];a.appendChild(b);b=this.createInput("Flurnummer:");this.fieldInput=b.children[0];this.fieldInput.addEventListener("keyup",this.onInputFieldKey.bind(this));
|
this.nameLoader=document.createElement("div");this.nameLoader.className="netgis-loader netgis-text-primary netgis-hide";this.nameLoader.innerHTML="<i class='fas fa-spinner'></i>";b.appendChild(this.nameLoader);this.nameList=document.createElement("ul");a.appendChild(this.nameList);b=this.createInput("Gemarkungsnummer:");this.districtInput=b.children[0];a.appendChild(b);b=this.createInput("Flurnummer:");this.fieldInput=b.children[0];this.fieldInput.addEventListener("keyup",this.onInputFieldKey.bind(this));
|
||||||
a.appendChild(b);b=this.createInput("<span>Flurst\u00fccksnummer (Z\u00e4hler/Nenner):</span>");this.parcelInputA=b.children[1];this.parcelInputA.style.width="48%";this.parcelInputB=this.parcelInputA.cloneNode(!0);this.parcelInputB.style.marginLeft="4%";b.appendChild(this.parcelInputB);a.appendChild(b);b=document.createElement("button");b.setAttribute("type","button");b.addEventListener("click",this.onParcelSearchClick.bind(this));b.className="netgis-color-a netgis-hover-c";b.innerHTML="Flurst\u00fccke suchen";
|
a.appendChild(b);b=this.createInput("<span>Flurst\u00fccksnummer (Z\u00e4hler/Nenner):</span>");this.parcelInputA=b.children[1];this.parcelInputA.style.width="48%";this.parcelInputB=this.parcelInputA.cloneNode(!0);this.parcelInputB.style.marginLeft="4%";b.appendChild(this.parcelInputB);a.appendChild(b);b=document.createElement("button");b.setAttribute("type","button");b.addEventListener("click",this.onParcelSearchClick.bind(this));b.className="netgis-color-a netgis-hover-c";b.innerHTML="Flurst\u00fccke suchen";
|
||||||
@@ -229,8 +231,8 @@ netgis.SearchParcel.prototype.attach=function(a){a.appendChild(this.container)};
|
|||||||
netgis.SearchParcel.prototype.createNameItem=function(a){var b=document.createElement("li"),c=document.createElement("button");c.setAttribute("type","button");c.addEventListener("click",this.onNameItemClick.bind(this));c.className="netgis-color-e netgis-hover-a netgis-text-a netgis-hover-text-e";c.innerHTML=a;b.appendChild(c);return b};
|
netgis.SearchParcel.prototype.createNameItem=function(a){var b=document.createElement("li"),c=document.createElement("button");c.setAttribute("type","button");c.addEventListener("click",this.onNameItemClick.bind(this));c.className="netgis-color-e netgis-hover-a netgis-text-a netgis-hover-text-e";c.innerHTML=a;b.appendChild(c);return b};
|
||||||
netgis.SearchParcel.prototype.createTable=function(a){var b=document.createElement("div");b.className="netgis-table-wrapper";var c=document.createElement("table");b.appendChild(c);var d=document.createElement("thead");c.appendChild(d);var e=document.createElement("tr");e.className="netgis-color-d netgis-shadow";d.appendChild(e);for(d=0;d<a.length;d++){var f=document.createElement("th");f.innerHTML=a[d];e.appendChild(f)}a=document.createElement("tbody");c.appendChild(a);return b};
|
netgis.SearchParcel.prototype.createTable=function(a){var b=document.createElement("div");b.className="netgis-table-wrapper";var c=document.createElement("table");b.appendChild(c);var d=document.createElement("thead");c.appendChild(d);var e=document.createElement("tr");e.className="netgis-color-d netgis-shadow";d.appendChild(e);for(d=0;d<a.length;d++){var f=document.createElement("th");f.innerHTML=a[d];e.appendChild(f)}a=document.createElement("tbody");c.appendChild(a);return b};
|
||||||
netgis.SearchParcel.prototype.createParcelItem=function(a,b,c,d,e,f,g){var h=document.createElement("tr");h.className="netgis-hover-light netgis-hover-text-primary";h.setAttribute("title","Klicken zum zoomen");h.setAttribute("data-id",d);h.setAttribute("data-field",a);h.setAttribute("data-parcel-a",b);h.setAttribute("data-parcel-b",c);h.setAttribute("data-bbox",f);h.setAttribute("data-geom",g);h.addEventListener("pointerenter",this.onParcelEnter.bind(this));h.addEventListener("pointerleave",this.onParcelLeave.bind(this));
|
netgis.SearchParcel.prototype.createParcelItem=function(a,b,c,d,e,f,g){var h=document.createElement("tr");h.className="netgis-hover-light netgis-hover-text-primary";h.setAttribute("title","Klicken zum zoomen");h.setAttribute("data-id",d);h.setAttribute("data-field",a);h.setAttribute("data-parcel-a",b);h.setAttribute("data-parcel-b",c);h.setAttribute("data-bbox",f);h.setAttribute("data-geom",g);h.addEventListener("pointerenter",this.onParcelEnter.bind(this));h.addEventListener("pointerleave",this.onParcelLeave.bind(this));
|
||||||
h.addEventListener("click",this.onParcelClick.bind(this));f=document.createElement("td");h.appendChild(f);g=document.createElement("button");g.setAttribute("type","button");g.setAttribute("title","Geometrie \u00fcbernehmen");g.addEventListener("click",this.onParcelImportClick.bind(this));g.className="netgis-text-primary netgis-hover-primary";g.innerHTML="<i class='fas fa-paste'></i>";f.appendChild(g);f=document.createElement("td");f.innerHTML=a;h.appendChild(f);a=document.createElement("td");a.innerHTML=
|
h.addEventListener("click",this.onParcelClick.bind(this));f=document.createElement("td");h.appendChild(f);this.client.editable&&(g=document.createElement("button"),g.setAttribute("type","button"),g.setAttribute("title","Geometrie \u00fcbernehmen"),g.addEventListener("click",this.onParcelImportClick.bind(this)),g.className="netgis-text-primary netgis-hover-primary",g.innerHTML="<i class='fas fa-paste'></i>",f.appendChild(g));f=document.createElement("td");f.innerHTML=a;h.appendChild(f);a=document.createElement("td");
|
||||||
b;h.appendChild(a);b=document.createElement("td");b.innerHTML=c;h.appendChild(b);c=document.createElement("td");c.innerHTML=d;h.appendChild(c);d=document.createElement("td");d.innerHTML=e;h.appendChild(d);return h};
|
a.innerHTML=b;h.appendChild(a);b=document.createElement("td");b.innerHTML=c;h.appendChild(b);c=document.createElement("td");c.innerHTML=d;h.appendChild(c);d=document.createElement("td");d.innerHTML=e;h.appendChild(d);return h};
|
||||||
netgis.SearchParcel.prototype.reset=function(){this.hideBottom();this.nameLoader.classList.add("netgis-hide");this.nameInput.value="";this.districtInput.value="";this.fieldInput.value="";this.parcelInputA.value="";this.parcelInputB.value="";this.nameList.innerHTML="";this.parcelInfo.innerHTML="";this.parcelList.innerHTML="";this.parcelTable.classList.add("netgis-hide");this.parcelReset.classList.add("netgis-hide");this.parcelCount.innerHTML="";var a=this;window.setTimeout(function(){a.top.scrollTop=
|
netgis.SearchParcel.prototype.reset=function(){this.hideBottom();this.nameLoader.classList.add("netgis-hide");this.nameInput.value="";this.districtInput.value="";this.fieldInput.value="";this.parcelInputA.value="";this.parcelInputB.value="";this.nameList.innerHTML="";this.parcelInfo.innerHTML="";this.parcelList.innerHTML="";this.parcelTable.classList.add("netgis-hide");this.parcelReset.classList.add("netgis-hide");this.parcelCount.innerHTML="";var a=this;window.setTimeout(function(){a.top.scrollTop=
|
||||||
0;a.parcelTable.scrollTop=0},10);netgis.util.invoke(this.container,netgis.Events.PARCELS_RESET,null)};netgis.SearchParcel.prototype.onInputNameKey=function(a){switch(a.keyCode){case 13:this.selectFirstName();break;case 27:this.reset();break;default:this.requestName(this.nameInput.value.trim())}};
|
0;a.parcelTable.scrollTop=0},10);netgis.util.invoke(this.container,netgis.Events.PARCELS_RESET,null)};netgis.SearchParcel.prototype.onInputNameKey=function(a){switch(a.keyCode){case 13:this.selectFirstName();break;case 27:this.reset();break;default:this.requestName(this.nameInput.value.trim())}};
|
||||||
netgis.SearchParcel.prototype.requestName=function(a){this.nameDebounce&&window.clearTimeout(this.nameDebounce);if(0!==a.length){var b=this.config.searchParcel.nameURL;b=netgis.util.replace(b,"{q}",window.encodeURIComponent(a));this.nameDebounce=window.setTimeout(this.onInputNameDebounce.bind(this,b),200);this.nameLoader.classList.remove("netgis-hide")}};netgis.SearchParcel.prototype.onInputNameDebounce=function(a){netgis.util.request(a,this.onInputNameResponse.bind(this))};
|
netgis.SearchParcel.prototype.requestName=function(a){this.nameDebounce&&window.clearTimeout(this.nameDebounce);if(0!==a.length){var b=this.config.searchParcel.nameURL;b=netgis.util.replace(b,"{q}",window.encodeURIComponent(a));this.nameDebounce=window.setTimeout(this.onInputNameDebounce.bind(this,b),200);this.nameLoader.classList.remove("netgis-hide")}};netgis.SearchParcel.prototype.onInputNameDebounce=function(a){netgis.util.request(a,this.onInputNameResponse.bind(this))};
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ class UserAdmin(admin.ModelAdmin):
|
|||||||
"is_staff",
|
"is_staff",
|
||||||
"is_superuser",
|
"is_superuser",
|
||||||
"api_token",
|
"api_token",
|
||||||
|
"oauth_token",
|
||||||
"groups",
|
"groups",
|
||||||
"notifications",
|
"notifications",
|
||||||
"date_joined",
|
"date_joined",
|
||||||
|
|||||||
20
user/migrations/0009_user_oauth_token.py
Normal file
20
user/migrations/0009_user_oauth_token.py
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
# Generated by Django 5.0.4 on 2024-04-30 07:20
|
||||||
|
|
||||||
|
import django.db.models.deletion
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('api', '0003_oauthtoken'),
|
||||||
|
('user', '0008_alter_user_id'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='user',
|
||||||
|
name='oauth_token',
|
||||||
|
field=models.ForeignKey(blank=True, db_comment='OAuth token for the user', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='api.oauthtoken'),
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -9,7 +9,7 @@ from django.contrib.auth.models import AbstractUser
|
|||||||
|
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
|
||||||
from api.models import APIUserToken
|
from api.models import APIUserToken, OAuthToken
|
||||||
from konova.settings import ZB_GROUP, DEFAULT_GROUP, ETS_GROUP
|
from konova.settings import ZB_GROUP, DEFAULT_GROUP, ETS_GROUP
|
||||||
from konova.utils.mailer import Mailer
|
from konova.utils.mailer import Mailer
|
||||||
from user.enums import UserNotificationEnum
|
from user.enums import UserNotificationEnum
|
||||||
@@ -24,6 +24,14 @@ class User(AbstractUser):
|
|||||||
help_text="The user's API token",
|
help_text="The user's API token",
|
||||||
on_delete=models.SET_NULL
|
on_delete=models.SET_NULL
|
||||||
)
|
)
|
||||||
|
oauth_token = models.ForeignKey(
|
||||||
|
"api.OAuthToken",
|
||||||
|
blank=True,
|
||||||
|
null=True,
|
||||||
|
on_delete=models.SET_NULL,
|
||||||
|
db_comment="OAuth token for the user",
|
||||||
|
related_name="+"
|
||||||
|
)
|
||||||
|
|
||||||
def is_notification_setting_set(self, notification_enum: UserNotificationEnum):
|
def is_notification_setting_set(self, notification_enum: UserNotificationEnum):
|
||||||
return self.notifications.filter(
|
return self.notifications.filter(
|
||||||
@@ -214,4 +222,46 @@ class User(AbstractUser):
|
|||||||
shared_teams = self.teams.filter(
|
shared_teams = self.teams.filter(
|
||||||
deleted__isnull=True
|
deleted__isnull=True
|
||||||
)
|
)
|
||||||
return shared_teams
|
return shared_teams
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def oauth_update_user(user_data: dict):
|
||||||
|
"""
|
||||||
|
Get or create a user depending on given user_data.
|
||||||
|
If the user record already exists, it's data will be updated using user_data.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
user_data (dict): User data from OAuth SSO component
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
user (User): The resolved user
|
||||||
|
"""
|
||||||
|
username = user_data.get("username")
|
||||||
|
user, is_created = User.objects.get_or_create(
|
||||||
|
username=username
|
||||||
|
)
|
||||||
|
|
||||||
|
if is_created:
|
||||||
|
user.set_unusable_password()
|
||||||
|
|
||||||
|
user.first_name = user_data.get("first_name")
|
||||||
|
user.last_name = user_data.get("last_name")
|
||||||
|
user.email = user_data.get("email")
|
||||||
|
|
||||||
|
return user
|
||||||
|
|
||||||
|
def oauth_replace_token(self, token: OAuthToken):
|
||||||
|
"""
|
||||||
|
Drops old token (if existing) and stores given token.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
token (OAuthToken): New token
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
user (User)
|
||||||
|
"""
|
||||||
|
if self.oauth_token:
|
||||||
|
self.oauth_token.delete()
|
||||||
|
self.oauth_token = token
|
||||||
|
self.save()
|
||||||
|
return self
|
||||||
@@ -9,11 +9,13 @@ from django.urls import path
|
|||||||
|
|
||||||
from user.autocomplete.share import ShareUserAutocomplete, ShareTeamAutocomplete
|
from user.autocomplete.share import ShareUserAutocomplete, ShareTeamAutocomplete
|
||||||
from user.autocomplete.team import TeamAdminAutocomplete
|
from user.autocomplete.team import TeamAdminAutocomplete
|
||||||
from user.views import *
|
from user.views.propagate import PropagateUserView
|
||||||
|
from user.views.views import *
|
||||||
|
|
||||||
app_name = "user"
|
app_name = "user"
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path("", index_view, name="index"),
|
path("", index_view, name="index"),
|
||||||
|
path("propagate/", PropagateUserView.as_view(), name="propagate"),
|
||||||
path("notifications/", notifications_view, name="notifications"),
|
path("notifications/", notifications_view, name="notifications"),
|
||||||
path("token/api", api_token_view, name="api-token"),
|
path("token/api", api_token_view, name="api-token"),
|
||||||
path("contact/<id>", contact_view, name="contact"),
|
path("contact/<id>", contact_view, name="contact"),
|
||||||
|
|||||||
7
user/views/__init__.py
Normal file
7
user/views/__init__.py
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
"""
|
||||||
|
Author: Michel Peltriaux
|
||||||
|
Organization: Struktur- und Genehmigungsdirektion Nord, Rhineland-Palatinate, Germany
|
||||||
|
Contact: ksp-servicestelle@sgdnord.rlp.de
|
||||||
|
Created on: 10.05.24
|
||||||
|
|
||||||
|
"""
|
||||||
69
user/views/propagate.py
Normal file
69
user/views/propagate.py
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
"""
|
||||||
|
Author: Michel Peltriaux
|
||||||
|
Organization: Struktur- und Genehmigungsdirektion Nord, Rhineland-Palatinate, Germany
|
||||||
|
Contact: ksp-servicestelle@sgdnord.rlp.de
|
||||||
|
Created on: 10.05.24
|
||||||
|
|
||||||
|
"""
|
||||||
|
import base64
|
||||||
|
import hashlib
|
||||||
|
import json
|
||||||
|
|
||||||
|
from cryptography.fernet import Fernet
|
||||||
|
from django.core.exceptions import ObjectDoesNotExist
|
||||||
|
from django.http import HttpRequest, JsonResponse
|
||||||
|
from django.utils.decorators import method_decorator
|
||||||
|
from django.views import View
|
||||||
|
from django.views.decorators.csrf import csrf_exempt
|
||||||
|
|
||||||
|
from konova.sub_settings.sso_settings import OAUTH_CLIENT_ID
|
||||||
|
from user.models import User
|
||||||
|
|
||||||
|
|
||||||
|
class PropagateUserView(View):
|
||||||
|
""" Receives user data to be stored in db
|
||||||
|
|
||||||
|
Used if new user gets access to application and needs to be created in application before first login (e.g.
|
||||||
|
proper rights management)
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
@method_decorator(csrf_exempt)
|
||||||
|
def dispatch(self, request, *args, **kwargs):
|
||||||
|
return super().dispatch(request, *args, **kwargs)
|
||||||
|
|
||||||
|
def post(self, request: HttpRequest, *args, **kwargs):
|
||||||
|
# Decrypt
|
||||||
|
encrypted_body = request.body
|
||||||
|
hash = hashlib.md5()
|
||||||
|
hash.update(OAUTH_CLIENT_ID.encode("utf-8"))
|
||||||
|
key = base64.urlsafe_b64encode(hash.hexdigest().encode("utf-8"))
|
||||||
|
fernet = Fernet(key)
|
||||||
|
body = fernet.decrypt(encrypted_body).decode("utf-8")
|
||||||
|
body = json.loads(body)
|
||||||
|
|
||||||
|
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)
|
||||||
|
except ObjectDoesNotExist:
|
||||||
|
user = User(**body)
|
||||||
|
status = "created"
|
||||||
|
user.set_unusable_password()
|
||||||
|
user.save()
|
||||||
|
|
||||||
|
data = {
|
||||||
|
"success": True,
|
||||||
|
"status": status
|
||||||
|
}
|
||||||
|
|
||||||
|
return JsonResponse(data)
|
||||||
Reference in New Issue
Block a user