Une API permettant à des manifestants d'enregistrer et de s'inscrire à une manifestation dans le but de s'auto-compter.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

7.6 KiB

Protest'O'Meter

A web API allowing protesters to count themselves.

Install

Prerequities

  • Postgres
  • GIS extension for Postgres
  • Python3

Installation

Once you have fullfilled the above requirements:

Install required python modules

$ cd ./protestometer_api
$ # OPTIONNAL
$ virtualenv .venv
$ source .venv/bin/activate
$ # /OPTIONNAL
$ pip3 install falcon
$ pip3 install gunicorn
$ pip3 install pyscopg2
$ pip3 install pytz

Clone the protestometer_api git repository:

$ git clone http://git.redatomik.org:/python/falcon/protestometer_api

Run protestometer_api with gunicorn

You may set a reverse proxy as a frontend for production use.

In the protestometer_api, run the following command

gunicorn -c gunicorn.config.py api.app

Play with protestometer_api

Protester_api comes with a demo script that tests all api end-points.

This script is known to be somewhat buggy. Use with care.

python3 protester_demo.py

API endpoints (W.I.P)

Protests

Method: GET
Route: /protests
Mandatory: None
Optional: None
Return: <JSON>
  method: <string>
  obj_name: <string>
  obj_type: <string>
  result: <string> ['error'|'success']
  response: <dict> 
    <int> protest_id: <dict>
      nom: <string>
      description: <string>
      start_date: <string>
      expire_date: <string>
    [...]
Method: GET
Route: /protests/<ID>/<OWNER>
Mandatory: None
Optional: None
Return: <JSON>
  method: <string>
  obj_name: <string>
  obj_type: <string>
  result: <string> ['error'|'success']
  response: <dict> 
    id: <int>
    nom: <string>
    description: <string>
    start_date: <string>
    expire_date: <string>
Method: PUT
Route: /protests
Mandatory: <string> nom, <string> description, <string> start_date [YYYYmmddHHMM], <string> expire_date [YYYYmmddHHMM]
Optional: None
Return: <JSON>
  method: <string>
  obj_name: <string>
  obj_type: <string>
  result: <string> ['error'|'success']
  response: <dict> 
    id: <int>
    nom: <string>
    description: <string>
    start_date: <string>
    expire_date: <string>

Method: PATCH
Route: /protests/<ID>/<OWNER>
Mandatory: <int> owner (owner id MUST be given in URL and in data parameters)
Optional: <string> nom, <string> description, <string> start_date [YYYYmmddHHMM], <string> expire_date [YYYYmmddHHMM]
Return: <JSON>
  method: <string>
  obj_name: <string>
  obj_type: <string>
  result: <string> ['error'|'success']
  response: <dict> 
    id: <int>
    nom: <string>
    description: <string>
    start_date: <string>
    expire_date: <string>
Method: DELETE
Route: /protests/<ID>/<OWNER>
Mandatory: None
Optional: None
Return: <JSON>
  method: <string>
  obj_name: <string>
  obj_type: <string>
  result: <string> ['error'|'success']
  response: <dict> 
    id: <int>
    nom: <string>
    description: <string>
    start_date: <string>
    expire_date: <string>

Protesters

Method: PUT
Route: /protesters
Mandatory:  <uuid> protester_uid, <float> lon, <float> lat
Optional: None
Return: <JSON>
  method: <string>
  obj_name: <string>
  obj_type: <string>
  result: <string> ['error'|'success']
  response: <dict> 
    protester_id: <int>
    potester_uid: <uuid>
    lon: <float>
    lat: <float>
    last_seen: <datetime>
    rgid: <int>
    dgid: <int>
    cgid: <int>
Method: GET
Route: /protesters/<UUID>
Mandatory: None
Optional: None
Return: <JSON>
  method: <string>
  obj_name: <string>
  obj_type: <string>
  result: <string> ['error'|'success']
  response: <dict> 
      protester_id: <int>
      potester_uid: <uuid>
      lon: <float>
      lat: <float>
      last_seen: <datetime>
      rgid: <int>
      dgid: <int>
      cgid: <int>
Method: PATCH
Route: /protesters/<UUID>
Mandatory: None
Optional: <float> lon, <float> lat
Return: <JSON>
  method: <string>
  obj_name: <string>
  obj_type: <string>
  result: <string> ['error'|'success']
  response: <dict> 
    protester_id: <int>
    potester_uid: <uuid>
    lon: <float>
    lat: <float>
    last_seen: <datetime>
    rgid: <int>
    dgid: <int>
    cgid: <int>
    
Method: DELETE
Route: /protesters/<UUID>
Mandatory: None
Optional: None
Return: <JSON>
  method: <string>
  obj_name: <string>
  obj_type: <string>
  result: <string> ['error'|'success']
  response: <dict> 
    protester_id: <int>
    potester_uid: <uuid>
    lon: <float>
    lat: <float>
    last_seen: <datetime>
    rgid: <int>
    dgid: <int>
    cgid: <int>

subscriptions

Method: GET
Route: /subscriptions
Mandatory: <int> protester_id
Optional: None
Return: <JSON>
  method: <string>
  obj_name: <string>
  obj_type: <string>
  result: <string> ['error'|'success']
  response: <dict> 
    <int> protest_id: <dict>
      protester_id: <int>
      subscription_date: <string>
      name: <string>
      descritpion: <string>
Method: PUT
Route: /subscriptions/<protest_id>/<protester_id>
Mandatory: None
Optional: None
Return: <JSON>
  method: <string>
  obj_name: <string>
  obj_type: <string>
  result: <string> ['error'|'success']
  response: <dict> 
    protest_id: <int>
    protester_id: <int>
    subscription_date: <string>
Method: DELETE
Route: /subscriptions/<protest_id>/<protester_id>
Mandatory: None
Optional: None
Return: <JSON>
  method: <string>
  obj_name: <string>
  obj_type: <string>
  result: <string> ['error'|'success']
  response: <dict> 
    protest_id: <int>
    protester_id: <int>
    subscription_date: <string>

Regions

Method: GET
Route: /regions
Mandatory: None
Optional: None
Return: <JSON>
  action: <string>
  type: <string>
  result: <string> ['error'|'success']
  response: <dict> 
    <int> rgid: <dict>
      code_insee: <int>
      nom: <string>
      lon: <float>
      lat: <float>
    [...]
Method: GET
Route: /regions/<rgid>
Mandatory: None
Optional: None
Return: <JSON>
  action: <string>
  type: <string>
  result: <string> ['error'|'success']
  response: <dict> 
    rgid: <int>
    code_insee: <int>
    nom: <string>
    lon: <float>
    lat: <float>
    [...]

Departements

Method: GET
Route: /departements
Mandatory: None
Optional: <int> rgid
Return: <JSON>
  action: <string>
  type: <string>
  result: <string> ['error'|'success']
  response: <dict> 
    <int> dgid: <dict>
      rgid: <int>
      code_insee: <int>
      nom: <string>
      lon: <float>
      lat: <float>
    [...]
Method: GET
Route: /departements/<dgid>
Mandatory: None
Optional: None
Return: <JSON>
  action: <string>
  type: <string>
  result: <string> ['error'|'success']
  response: <dict> 
    dgig: <int>
    rgid: <int>
    code_insee: <int>
    nom: <string>
    lon: <float>
    lat: <float>
    [...]

Communes

Method: GET
Route: /communes
Mandatory: None
Optional: <int> rgid, <int> dgid
Return: <JSON>
  action: <string>
  type: <string>
  result: <string> ['error'|'success']
  response: <dict> 
    <int> cgid: <dict>
      rgid: <int>
      dgid: <int>
      code_insee: <int>
      nom: <string>
      lon: <float>
      lat: <float>
    [...]
Method: GET
Route: /communes/<cgid>
Mandatory: None
Optional: None
Return: <JSON>
  action: <string>
  type: <string>
  result: <string> ['error'|'success']
  response: <dict>
    cgid: <int>
    rgid: <int>
    dgid: <int>
    code_insee: <int>
    nom: <string>
    lon: <float>
    lat: <float>
    [...]

Counters

Method: GET
Route: /communes/<type> [regions|departements|communes]
Mandatory: None
Optional: <int> rgid, <int> dgid, <int> cgid
Return: <JSON>
  action: <string>
  type: <string>
  result: <string> ['error'|'success']
  response: <dict> 
    <int> gid: <dict>
      rgid|dgid|cgid: <int>
      nom: <string>
      cpt: <int>
    [...]