2016-04-14 17:46:30 +02:00
# backend.py
# openeventdatabase
2016-05-04 19:22:56 +02:00
import os
2016-04-14 17:46:30 +02:00
import falcon
import psycopg2
import uuid
2016-04-14 19:05:59 +02:00
import json
2016-04-14 17:46:30 +02:00
2016-05-04 19:22:56 +02:00
def db_connect ( ) :
db_host = os . getenv ( " DB_HOST " , " localhost " )
db_password = os . getenv ( " POSTGRES_PASSWORD " , " " )
db = psycopg2 . connect ( dbname = " oedb " , host = db_host , password = db_password , user = " postgres " )
return db
2016-04-14 17:46:30 +02:00
class StatsResource ( object ) :
def on_get ( self , req , resp ) :
2016-05-04 19:22:56 +02:00
db = db_connect ( )
2016-04-14 17:46:30 +02:00
cur = db . cursor ( )
2016-04-20 07:48:58 +02:00
cur . execute ( " SELECT count(*) as events_count, max(createdate) as last_created, max(lastupdate) as last_updated from events; " )
2016-04-14 17:46:30 +02:00
stat = cur . fetchone ( )
cur . close ( )
db . close ( )
2016-04-20 07:48:58 +02:00
resp . body = """ { " events_count " : %s , " last_created " : " %s " , " last_updated " : " %s " } """ % ( stat [ 0 ] , stat [ 1 ] , stat [ 2 ] )
2016-04-14 17:46:30 +02:00
resp . set_header ( ' X-Powered-By ' , ' OpenEventDatabase ' )
resp . set_header ( ' Access-Control-Allow-Origin ' , ' * ' )
resp . set_header ( ' Access-Control-Allow-Headers ' , ' X-Requested-With ' )
resp . status = falcon . HTTP_200
2016-04-14 19:05:59 +02:00
class EventResource ( object ) :
2016-04-30 23:50:28 +02:00
def on_get ( self , req , resp , id ) :
2016-05-04 19:22:56 +02:00
db = db_connect ( )
2016-04-20 07:48:58 +02:00
cur = db . cursor ( )
2016-04-30 23:50:28 +02:00
# get event geojson Feature
cur . execute ( """
SELECT format ( ' { " type " : " Feature " , " properties " : ' | | events_tags : : text | | ' , " geometry " : ' | | st_asgeojson ( geom ) ) | | ' } '
FROM events
JOIN geo ON ( hash = events_geo )
WHERE events_id = % s ; """ , (id,))
e = cur . fetchone ( )
2016-04-20 07:48:58 +02:00
resp . set_header ( ' X-Powered-By ' , ' OpenEventDatabase ' )
resp . set_header ( ' Access-Control-Allow-Origin ' , ' * ' )
resp . set_header ( ' Access-Control-Allow-Headers ' , ' X-Requested-With ' )
2016-04-30 23:50:28 +02:00
if e is not None :
resp . body = e [ 0 ]
resp . status = falcon . HTTP_200
else :
resp . status = falcon . HTTP_404
2016-04-20 07:48:58 +02:00
db . close ( )
2016-04-14 19:05:59 +02:00
def on_post ( self , req , resp ) :
2016-05-03 17:11:43 +02:00
resp . set_header ( ' X-Powered-By ' , ' OpenEventDatabase ' )
resp . set_header ( ' Access-Control-Allow-Origin ' , ' * ' )
resp . set_header ( ' Access-Control-Allow-Headers ' , ' X-Requested-With ' )
2016-04-30 23:50:28 +02:00
# get request body payload (geojson Feature)
2016-04-14 19:05:59 +02:00
body = req . stream . read ( ) . decode ( ' utf-8 ' )
j = json . loads ( body )
2016-05-03 17:11:43 +02:00
if " properties " not in j or " geometry " not in j :
resp . body = " missing ' geometry ' or ' properties ' elements "
resp . status = falcon . HTTP_400
if " start " not in j [ ' properties ' ] :
event_start = j [ ' properties ' ] [ ' when ' ]
else :
event_start = j [ ' properties ' ] [ ' start ' ]
if " stop " not in j [ ' properties ' ] :
event_stop = j [ ' properties ' ] [ ' when ' ]
else :
event_stop = j [ ' properties ' ] [ ' stop ' ]
if event_start == event_stop :
when = " [ " + event_start + " , " + event_stop + " ] "
else :
when = " [ " + event_start + " , " + event_stop + " ) "
2016-04-14 19:05:59 +02:00
# connect to db and insert
2016-05-04 19:22:56 +02:00
db = db_connect ( )
2016-04-14 19:05:59 +02:00
cur = db . cursor ( )
2016-04-30 23:50:28 +02:00
# get the geometry part
geometry = json . dumps ( j [ ' geometry ' ] )
# insert into geo table if not existing
cur . execute ( """ INSERT INTO geo (hash, geom) SELECT * FROM (SELECT md5(ewkt) as hash, st_setsrid(st_geomfromewkt(ewkt),4326) as geom FROM (SELECT st_asewkt(st_geomfromgeojson( %s )) as ewkt) as g) as i ON CONFLICT DO NOTHING RETURNING hash; """ , ( geometry , ) )
# get its id (md5 hash)
h = cur . fetchone ( )
if h is None :
cur . execute ( """ SELECT md5(st_asewkt(st_geomfromgeojson( %s ))); """ , ( geometry , ) )
h = cur . fetchone ( )
2016-05-03 17:11:43 +02:00
cur . execute ( """ INSERT INTO events ( events_type, events_what, events_when, events_tags, events_geo) VALUES ( %s , %s , %s , %s , %s ) RETURNING events_id; """ , ( j [ ' properties ' ] [ ' type ' ] , j [ ' properties ' ] [ ' what ' ] , when , json . dumps ( j [ ' properties ' ] ) , h [ 0 ] ) )
2016-04-14 19:05:59 +02:00
# get newly created event id
e = cur . fetchone ( )
db . commit ( )
cur . close ( )
db . close ( )
# send back to client
resp . body = """ { " id " : " %s " } """ % ( e [ 0 ] )
2016-05-03 17:11:43 +02:00
resp . status = falcon . HTTP_201
2016-04-14 19:05:59 +02:00
2016-04-14 17:46:30 +02:00
# falcon.API instances are callable WSGI apps
app = falcon . API ( )
# Resources are represented by long-lived class instances
2016-04-14 19:05:59 +02:00
event = EventResource ( )
2016-04-14 17:46:30 +02:00
stats = StatsResource ( )
# things will handle all requests to the matching URL path
2016-04-30 23:50:28 +02:00
app . add_route ( ' /event/ {id} ' , event ) # handle single event requests
2016-04-14 19:05:59 +02:00
app . add_route ( ' /event ' , event ) # handle single event requests
2016-04-14 17:46:30 +02:00
app . add_route ( ' /stats ' , stats )