CYPEX Documentation
Wechsel zwischen Dunkel/Hell/Auto Modus Wechsel zwischen Dunkel/Hell/Auto Modus Wechsel zwischen Dunkel/Hell/Auto Modus Zurück zur Startseite Support

Known bugs and pending improvements

Known bugs and pending improvements

In this section we’ll discuss known bugs as well as features which are still missing and which might be implemented in the foreseeable future.

Security features

This section will discuss missing security related features which will be added to CYPEX in the future to make the product more comprehensive.

Ability to create nested roles

Currently it’s possible to create database roles in the admin panel. However, it’s not possible to assign those roles to other roles - yet. We’ll fix this in the future and make the feature more complete.

Provide an overview of permissions

In the future we’ll provide an easy-to-use overview, to give developers a better way to keep track of permissions. In addition to a complete list, we’re planning to create a diagram.

View handling

The following view-related issues are known and should be kept in mind to ensure smooth operation of CYPEX. Note that “queries” in CYPEX are stored as views on the database level to ensure dependency tracking as well as security abstractions.

CREATE VIEW … WITH CHECK OPTION

Currently CYPEX doesn’t use “WITH CHECK OPTION”. Why does it matter? Suppose you get a query that only shows “data in your country”. In case the query is simple, PostgreSQL will make it “auto-updatable” which means that you can INSERT, UPDATE, and DELETE. However, without the “WITH CHECK”-option you can theoretically insert data which cannot be seen later anymore (by adding data not in your country). This will be fixed in the future.

Views and dependencies

Since we’re using views to abstract the underlying data model from the GUI side of the app, you need to be aware that PostgreSQL will drop cascading objects. This is relevant because it can remove the data source needed by your app.

We are currently working on code to make dependency tracking easier and more transparent.

Security barrier views

At the moment we don’t use “security barriers” views for efficiency reasons. We therefore recommend not using stored procedures which make extensive use of RAISE NOTICE. Also make sure that functions which have side effects or use RAISE NOTICE are checked and marked as NOT LEAKPROOF.

Data type handling

Currently the “interval” data type isn’t fully supported under every circumstance. Therefore “interval” is mostly seen as text and does not offer any additional functionality which might be desired.

We’re working to remove this limitation.

GIS data handling

CYPEX supports GIS data. However, to render GIS data in the GUI, the query you are using has to provide the frontend with a GeoJSON.

There are currently two options to handle this:

  • Create a GeoJSON as part of a query
  • Use a ready-made GeoJSON column inside the underlying tables

Since GeoJSONs aren’t automatically generated by the default rendering process, you need to generate them as part of the query. The following queries contain examples which show how this can be done:

select
    inspection.id,
    tv.license_plate,
      tv.vehicle_model_id,
      tv.registered_country,
      ST_AsGeoJSON(gps_pos)::jsonb gps_pos,
      x.server_tstamp tracked_at,
      inspection.tstamp inspected_at,
      inspection.base_station_id,
      inspection.inspection_type_id,
      inspection.aggregate_status
    from backoffice.t_vehicle tv
        left join backoffice.t_vehicle_gps_device tvd
        on (tv.id=tvd.vehicle_id)
    left join lateral
      select
        g.id,
        g.gps_pos,
        g.server_tstamp
      from gps_track.t_track AS g
      where
        g.device_code = tvd.gps_device_id and
        g.server_tstamp > g.server_tstamp - interval ''1 week''
      order by g.server_tstamp desc LIMIT 1) x on true,
    lateral (
      select
        ti.id,
        ti.base_station_id,
        ti.tstamp,
        ti.inspection_type_id,
        ti.aggregate_status
      from backoffice.t_inspection ti
      where
        ti.vehicle_id = tv.id and
        ti.inspection_state = ''clean''
      order by ti.tstamp desc limit 1
    ) as inspection,
    backoffice.t_inspection_type tit
    where
      inspection.inspection_type_id=tit.id and
      tit.inspection_type = ''rent_out'' and
      (tvd.active is null or tvd.active)
    order by inspection.tstamp desc
SELECT
    json_build_object(
      'type', 'FeatureCollection',
      'features', data_danger_zone.tracks || ST_AsGeoJSON(data_danger_zone.*)::jsonb
    ) danger_zone_tracks
  from (
    select py.area_name as name,
      py.polygon as geom,
      jsonb_agg(ST_AsGeoJSON(pt.*)::jsonb) as tracks
    from (
      select vlt.license_plate, vlt.server_tstamp, vlt.gps_pos
  from  cypex_generated.v_vehicle_latest_gps_track vlt
      ) as pt
    JOIN (
      select a.*
      from
        backoffice.t_danger_area a,
        backoffice.t_area_type b
      where a.area_type_id=b.id and b.area_type = 'danger_area'
      and now() between a.active_from and a.active_until
    ) py ON ST_Intersects(py.polygon, pt.gps_pos)
    group by py.area_name, py.polygon
  ) as data_danger_zone

In this case, the ST_AsGeoJSON function did the magic. But here’s one more example:

with stations_fence as (
        select
          ST_Union(ST_Buffer(ta.gps, 50000)::geometry) as fence
          FROM backoffice.t_base_station tbs inner join backoffice.t_address ta
    on (tbs.address_id=ta.id)
      ), violated_tracks as (
        select
          jsonb_agg(json_build_object(
              ''type'', ''Feature'',
              ''geometry'', ST_AsGeoJSON(tt.gps_pos)::jsonb,
              ''properties'', json_build_object(
              ''license_plate'', tv.license_plate,
              ''registered_country'', tv.registered_country,
              ''tracked_at'', tt.server_tstamp
            )))::jsonb as tracks
        from
          gps_track.t_track tt inner join
          backoffice.t_vehicle_gps_device vd on (tt.device_code = vd.gps_device_id)
          inner join backoffice.t_vehicle tv on(vd.vehicle_id=tv.id),
          stations_fence
        where
          not ST_Intersects(stations_fence.fence, tt.gps_pos)
          and  tt.server_tstamp > tt.server_tstamp - interval ''1 month''
      )
      select
        violated_tracks.tracks || ST_AsGeoJSON(stations_fence.fence)::jsonb
    as violated_tracks
      from stations_fence, violated_tracks

Take note that in case of a default query (= “SELECT * FROM tab”), you don’t have to worry about INSERT, UPDATE, and DELETE. PostgreSQL knows that the view is auto-updatable and you don’t have to add additional code. However, this isn’t true in case of a query that generates a GeoJSON.

A trigger has to be added on top of the query (= view) to teach PostgreSQL how to modify data. Note this view isn’t auto-updatable anymore, and therefore the way back to the table has to be defined by developers.

The following listing shows how such triggers can be made:

CREATE OR REPLACE FUNCTION danger_area_fn() RETURNS TRIGGER
AS $$
  DECLARE
    _polygon backoffice.t_danger_area.polygon%type;
    new_return record;
  BEGIN
    if new.polygon isn't null then
      select ST_GeomFromGeoJSON(coalesce(new.polygon::json->'features'->0->'geometry', new.polygon::json)) into _polygon;
    end if;
    IF (TG_OP = 'INSERT') THEN
      INSERT INTO backoffice.t_danger_area(
        area_name,
        polygon,
        reason,
        active_from,
        active_until,
        area_type_id
      ) VALUES (
        new.area_name,
        _polygon,
        new.reason,
        new.active_from,
        new.active_until,
        new.area_type_id
      );
      select
        * into new_return
      from cypex_generated.v_backoffice_t_danger_area
      where id = currval('backoffice.t_danger_area_id_seq'::regclass);
      return new_return;
    END IF;
    IF (TG_OP = 'UPDATE') THEN
      UPDATE backoffice.t_danger_area SET
        area_name = new.area_name,
        polygon = _polygon,
        reason = new.reason,
        active_from = new.active_from,
        active_until = new.active_until,
        area_type_id = new.area_type_id
      WHERE id=new.id;
      return new;
    END IF;
    IF (TG_OP = 'DELETE') then
      delete from backoffice.t_danger_area where id = old.id;
    END IF;
    return null;
  END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER t_danger_area_trigger
  INSTEAD OF INSERT OR UPDATE OR DELETE ON cypex_generated.v_backoffice_t_danger_area
  FOR EACH ROW
  EXECUTE PROCEDURE danger_area_fn();

If you want to know more about triggers in PostgreSQL, check out the PostgreSQL documentation..

At this point it’s not yet possible to create data models from scratch inside the admin panel. We’re working hard to fix this issue in the next release.

Missing model creation

You’ll soon be able to create models from scratch and you’ll be able to define triggers on “queries” to make it easier to insert and update more complicated operations. You will also make better use of the information available inside the data model during default rendering.

Workflows and foreign keys

At the moment, foreign keys are defined on columns. In case states are derived from a column, take all existing values from this column. However, you often may be in a 1:n relationship, with the workflow playing out on the “n” side of the foreign key relation.

In future releases we’ll allow the workflow to take all possible keys from the “1” side of the join as the “n” side might not contain all values known to the “1” side of the relation.

Alternatively you should be able to specify some kind of data source to fetch all possible states from the existing model (especially important in case you’re dealing with more transitive or more complex models in general).

Pre-func and post-func enabled workflows

At this point you can transition from one state to the other. However, what if state changes should only happen under certain conditions? Let’s take a look at an example: A person applies for a bank loan. The loan is only granted in case some more complicated calculations give the OK. Currently it’s possible to do this using triggers. However, in the future our team will integrate this with workflows more tightly. The idea is to use “pre-funcs” and “post-funcs”. A pre-func will be called shortly after leaving a state to determine the target state (= loan will be granted or rejected based on some other data).

Graphical user interface

In this section we’ll discuss bugs and missing features related to the graphical user interface designer.

Multiple file uploads

At this point files have to be uploaded one by one. Multi-file uploads are currently not working. However, we’ll support this feature in the future.

Handling of password fields

At the moment CYPEX does not support HTML password fields. HTML Password fields do not show “letters” but use “dots” to hide the password. This will most likely be changed in the future.