def get_toponyms(self, req: gws.IWebRequest, p: GetToponymsParams) -> GetToponymsResponse: """Return all Toponyms (Gemeinde/Gemarkung/Strasse) in the area""" req.require_project(p.projectUid) res = self.provider.find_strasse(types.FindStrasseQuery(p)) gemeinde = {} gemarkung = {} for s in res.strassen: if s.gemeindeUid not in gemeinde: gemeinde[s.gemeindeUid] = ToponymGemeinde(name=re.sub( r'^Stadt\s+', '', s.gemeinde), uid=s.gemeindeUid) if s.gemarkungUid not in gemarkung: gemarkung[s.gemarkungUid] = ToponymGemarkung( name=s.gemarkung, uid=s.gemarkungUid, gemeindeUid=s.gemeindeUid) return GetToponymsResponse( gemeinden=sorted(gemeinde.values(), key=lambda x: x.name), gemarkungen=sorted(gemarkung.values(), key=lambda x: x.name), strasseNames=[s.strasse for s in res.strassen], strasseGemarkungUids=[s.gemarkungUid for s in res.strassen], )
def api_connect(self, req: gws.IWebRequest, p: ConnectParams) -> ConnectResponse: req.require_project(p.projectUid) shape = gws.lib.shape.union( gws.lib.shape.from_props(s) for s in p.shapes) request_id = self._new_request(shape) if not request_id: raise gws.base.web.error.NotFound() url = self.request_url.replace('{REQUEST_ID}', request_id) return ConnectResponse(url=url)
def _get_box(self, req: gws.IWebRequest, p: GetBoxParams) -> gws.BytesResponse: layer = req.require_layer(p.layerUid) content = None mri = gws.MapRenderInput( ) extra_params = {} if p.layers: extra_params['layers'] = p.layers view = gws.gis.render.map_view_from_bbox( crs=gws.gis.crs.get(p.crs) or layer.map.crs, bbox=p.bbox, size=(p.width, p.height, units.PX), dpi=units.OGC_SCREEN_PPI, rotation=0 ) ts = gws.time_start(f'RENDER_BOX layer={p.layerUid} view={view!r}') try: content = layer.render_box(view, extra_params) except: gws.log.exception() gws.time_end(ts) return self._image_response(content)
def export(self, req: gws.IWebRequest, p: ExportParams) -> ExportResponse: """Export Flurstueck features""" project = req.require_project(p.projectUid) fp = p.findParams fp.projectUid = project.uid fp.localeUid = p.localeUid res = self._find(req, fp, self.limit) if not res.features: raise gws.base.web.error.NotFound() combined_rules: t.List[gws.base.model.Rule] = [] group_indexes = sorted(int(i) for i in p.groupIndexes) for i in group_indexes: combined_rules.extend(self.export_groups[i].data_model.rules) combined_model = self.root.create_object( gws.base.model.Object, gws.Config(rules=combined_rules), shared=True, key=group_indexes) csv_bytes = util.export.to_csv(self, res.features, combined_model) return ExportResponse(content=csv_bytes, mime='text/csv')
def find_features(self, req: gws.IWebRequest, p: Params) -> Response: """Perform a search""" project = req.require_project(p.projectUid) bounds = gws.Bounds( crs=p.crs or project.map.crs, extent=p.bbox or project.map.extent, ) limit = self.limit if p.limit: limit = min(int(p.limit), self.limit) shapes = [] if p.shapes: shapes = [gws.gis.shape.from_props(s) for s in p.shapes] tolerance = None if p.tolerance: tolerance = gws.lib.units.parse(p.tolerance, default=gws.lib.units.PX) args = gws.SearchArgs( bounds=bounds, keyword=(p.keyword or '').strip(), layers=gws.compact( req.acquire('gws.ext.layer', uid) for uid in p.layerUids), limit=limit, project=project, resolution=p.resolution, shapes=shapes, tolerance=tolerance, ) found = runner.run(req, args) for f in found: # @TODO only pull specified props from a feature f.transform_to(args.bounds.crs) f.apply_templates() f.apply_data_model() return Response( features=[gws.props(f, req.user, context=self) for f in found])
def handle_request(self, req: gws.IWebRequest) -> gws.ContentResponse: # services can be configured globally (in which case, self.project == None) # and applied to multiple projects with the projectUid param # or, configured just for a single project (self.project != None) project = None p = req.param('projectUid') if p: project = req.require_project(p) if self.project and project != self.project: gws.log.debug(f'service={self.uid!r}: wrong project={p!r}') raise gws.base.web.error.NotFound('Project not found') elif self.project: # for in-project services, ensure the user can access the project project = req.require_project(self.project.uid) rd = Request(req=req, project=project) return self.dispatch_request(rd, req.param('request', ''))
def info(self, req: gws.IWebRequest, p: gws.Params) -> InfoResponse: """Return the project configuration""" project = req.require_project(p.projectUid) locale_uid = p.localeUid if locale_uid not in project.locale_uids: locale_uid = project.locale_uids[0] return InfoResponse( project=gws.props(project, req.user), locale=gws.lib.intl.locale(locale_uid), user=None if req.user.is_guest else gws.props(req.user, req.user))
def api_get_data(self, req: gws.IWebRequest, p: GetDataParams) -> GetDataResponse: req.require_project(p.projectUid) request_id = p.requestId geom = self._selection_for_request(request_id) if not geom: gws.log.warn(f'request {request_id!r} not found') raise gws.base.web.error.NotFound() self._populate_data_table() atts = self._select_data(request_id) shape = gws.lib.shape.from_wkb_hex(geom, self.alkis.crs) f = gws.lib.feature.Feature( uid=f'dprocon_{request_id}', attributes=atts, shape=shape, ) f.apply_templates(self.templates, {'title': self.var('infoTitle')}) return GetDataResponse(feature=f.props)
def _get_features(self, req: gws.IWebRequest, p: GetFeaturesParams) -> t.List[gws.IFeature]: layer = req.require_layer(p.layerUid) bounds = gws.Bounds( crs=gws.gis.crs.get(p.crs) or layer.map.crs, extent=p.get('bbox') or layer.map.extent ) found = layer.get_features(bounds, p.get('limit')) for f in found: f.transform_to(bounds.crs) f.apply_templates(subjects=['label', 'title']) f.apply_data_model() return found
def api_find_fs(self, req: gws.IWebRequest, p: GetFsParams) -> GetFsResponse: if not self.alkis: raise gws.base.web.error.NotFound() feature = self._find_alkis_feature(p) if not feature: raise gws.base.web.error.NotFound() project = req.require_project(p.projectUid) feature.transform_to(project.map.crs) f = feature.apply_templates(self.templates).props f.attributes = [] return GetFsResponse(feature=f)
def _parse_header(req: gws.IWebRequest): h = req.header('Authorization') if not h: return a = h.strip().split() if len(a) != 2 or a[0].lower() != 'basic': return try: b = gws.to_str(base64.decodebytes(gws.to_bytes(a[1]))) except ValueError: return c = b.split(':') if len(c) != 2: return return c
def print(self, req: gws.IWebRequest, p: PrintParams) -> gws.base.printer.types.StatusResponse: """Print Flurstueck features""" project = req.require_project(p.projectUid) fp = p.findParams fp.projectUid = project.uid fp.localeUid = p.localeUid res = self._find(req, fp, self.limit) if not res.features: raise gws.base.web.error.NotFound() pp = p.printParams pp.projectUid = p.projectUid pp.localeUid = p.localeUid pp.templateUid = self.print_template.uid pp.sections = [] for feature in res.features: if not feature.shape: gws.log.warn(f'feature {feature.uid!r} has no shape') continue center = feature.shape.centroid pp.sections.append( gws.base.printer.types.Section( center=[center.x, center.y], context=feature.template_context, items=[ gws.base.printer.types.ItemFeatures( type='features', features=[feature], style=p.highlightStyle, ) ])) job = gws.base.printer.job.start(req, pp) return gws.base.printer.job.status(job)
def _get_xyz(self, req: gws.IWebRequest, p: GetXyzParams) -> gws.BytesResponse: layer = req.require_layer(p.layerUid) content = None ts = gws.time_start(f'RENDER_XYZ layer={p.layerUid} xyz={p.x}/{p.y}/{p.z}') try: content = layer.render_xyz(p.x, p.y, p.z) except: gws.log.exception() gws.time_end(ts) # for public tiled layers, write tiles to the web cache # so they will be subsequently served directly by nginx if content and gws.is_public_object(layer) and layer.has_cache: path = gws.base.layer.layer_url_path(layer.uid, kind='tile') path = path.replace('{x}', str(p.x)) path = path.replace('{y}', str(p.y)) path = path.replace('{z}', str(p.z)) gws.gis.cache.store_in_web_cache(path, content) return self._image_response(content)
def _log_eigentuemer_access(self, req: gws.IWebRequest, p: FindFlurstueckParams, is_ok, total=0, features=None): if not self.log_table: gws.log.debug('_log_eigentuemer_access', is_ok, 'no log table!') return has_relevant_params = any( p.get(s) for s in self._log_eigentuemer_access_params) if is_ok and not has_relevant_params: gws.log.debug('_log_eigentuemer_access', is_ok, 'no relevant params!') return fs_ids = '' if features: fs_ids = ','.join(f.uid for f in features) data = { 'app_name': 'gws', 'date_time': gws.lib.date.now_iso(), 'ip': req.env('REMOTE_ADDR', ''), 'login': req.user.uid, 'user_name': req.user.display_name, 'control_input': (p.controlInput or '').strip(), 'control_result': 1 if is_ok else 0, 'fs_count': total, 'fs_ids': fs_ids } with self.provider.connection() as conn: conn.insert_one(self.log_table, 'id', data) gws.log.debug('_log_eigentuemer_access', is_ok, 'ok')
def handle_request(self, req: gws.IWebRequest) -> gws.ContentResponse: rd = core.Request(req=req, project=None, service=self) if req.method == 'GET': return self.dispatch_request( rd, req.param('request', default='record')) # CSW should accept POST'ed xml, which can be wrapped in a SOAP envelope try: rd.xml_element = xml2.from_string(req.text) except xml2.Error: raise gws.base.web.error.BadRequest() if rd.xml_element.name.lower() == 'envelope': rd.xml_is_soap = True try: rd.xml_element = xml2.first(xml2.first('body')) except Exception: raise gws.base.web.error.BadRequest() return self.dispatch_request( rd, xml2.unqualify_name(rd.xml_element.name.lower()))
def _serve_path(root: gws.IRoot, req: gws.IWebRequest, p: GetAssetParams, as_attachment=False): spath = str(p.get('path') or '') if not spath: raise gws.base.web.error.NotFound() site_assets = req.site.assets_root project = None project_assets = None project_uid = p.get('projectUid') if project_uid: project = req.require_project(project_uid) project_assets = project.assets_root rpath = None if project_assets: rpath = _abs_path(spath, project_assets.dir) if not rpath and site_assets: rpath = _abs_path(spath, site_assets.dir) if not rpath: raise gws.base.web.error.NotFound() locale_uid = p.localeUid if project and locale_uid not in project.locale_uids: locale_uid = project.locale_uids[0] tpl = gws.base.template.create_from_path(root, rpath) if tpl: # give the template an empty response to manipulate (e.g. add 'location') res = gws.ContentResponse() context = { 'project': project, 'projects': _projects_for_user(root, req.user), 'request': req, 'user': req.user, 'params': p, 'response': res, 'localeUid': locale_uid, } render_res = tpl.render(gws.TemplateRenderInput(context=context)) if gws.is_empty(res): res = render_res return res mime = gws.lib.mime.for_path(rpath) if not _valid_mime_type(mime, project_assets, site_assets): gws.log.error(f'invalid mime path={rpath!r} mime={mime!r}') # NB: pretend the file doesn't exist raise gws.base.web.error.NotFound() gws.log.debug(f'serving {rpath!r} for {spath!r}') return gws.ContentResponse(mime=mime, path=rpath, as_attachment=as_attachment)
def _get_legend(self, req: gws.IWebRequest, p: GetLegendParams) -> gws.BytesResponse: layer = req.require_layer(p.layerUid) content = gws.gis.legend.to_bytes(layer.render_legend_with_cache()) return self._image_response(content)
def describe_layer(self, req: gws.IWebRequest, p: DescribeLayerParams) -> DescribeLayerResponse: layer = req.require_layer(p.layerUid) return DescribeLayerResponse(description=layer.description)