Improve documentation. Fix #45.
This commit is contained in:
parent
06c02f6ece
commit
9beed09ed0
@ -16,7 +16,8 @@ well, if you are more comfortable speaking French.
|
|||||||
* In case of changes request, amend your commit.
|
* In case of changes request, amend your commit.
|
||||||
|
|
||||||
New issues and merge requests are better at
|
New issues and merge requests are better at
|
||||||
[Framagit](https://framagit.org/phyks/cyclassist).
|
[Framagit](https://framagit.org/phyks/cyclassist). If this is a blocking issue
|
||||||
|
for you, you can contribute through Github as well.
|
||||||
|
|
||||||
You can contribute in many ways to Cycl'Assist, be it development,
|
You can contribute in many ways to Cycl'Assist, be it development,
|
||||||
translations or simply communicating around about this webapp!
|
translations or simply communicating around about this webapp!
|
||||||
@ -43,12 +44,46 @@ python -m server
|
|||||||
|
|
||||||
to spawn the server-side part, listening on `localhost:8081`.
|
to spawn the server-side part, listening on `localhost:8081`.
|
||||||
|
|
||||||
|
You might want to have a look at [`doc/0.hosting.md`](doc/0.hosting.md) for
|
||||||
|
extra information on the available configuration options and general guidance
|
||||||
|
with hosting the software.
|
||||||
|
|
||||||
## Useful scripts for dev
|
|
||||||
|
|
||||||
You can run `scripts/gps_to_gpx.py` on your GPX trace to create a
|
## Adding new opendata sources
|
||||||
`src/tools/mock_gpx.json` file ready to be used as a mocking source for the
|
|
||||||
position data (just edit the `src/constants.js` file accordingly).
|
A few opendata files are already imported in Cycl'Assist. All the scripts to
|
||||||
|
fetch and import them are located under the `scripts/opendata` folder.
|
||||||
|
|
||||||
|
If you find any other opendata file which is not already imported and would be
|
||||||
|
worth having in Cycl'Assist, please feel free to edit the scripts under
|
||||||
|
`scripts/opendata` and create a merge request!
|
||||||
|
|
||||||
|
|
||||||
|
## Useful tips for contributors
|
||||||
|
|
||||||
|
### Mocking locations
|
||||||
|
|
||||||
|
A useful tool for dev on Cycl'Assist is the ability to mock location (instead
|
||||||
|
of using the location provided by your GPS or manual position). This is
|
||||||
|
possible by editing the values `src/constants.js` file. You can either
|
||||||
|
generate random positions in a bounding box or rely on a GPX file.
|
||||||
|
|
||||||
|
To mock position using a GPX file, there is one extra required step. You
|
||||||
|
should run `scripts/gps_to_gpx.py <GPX_FILE>` to create a file at
|
||||||
|
`src/tools/mock_gpx.json` which will be used as a mocking source
|
||||||
|
for the position data (provided the settings in `src/constants.js` require
|
||||||
|
mocking position using a GPX trace).
|
||||||
|
|
||||||
|
|
||||||
|
### _A la carte_ component
|
||||||
|
|
||||||
|
We are using [_A la carte_](https://vuetifyjs.com/en/guides/a-la-carte)
|
||||||
|
Vuetify components to reduce the size of the build.
|
||||||
|
|
||||||
|
If you then require new Vuetify components, check that they are indeed
|
||||||
|
included in the `src/vuetify.js` file. The `yarn list-vuetify-components`
|
||||||
|
command might be useful to help you determine which components are used across
|
||||||
|
the code.
|
||||||
|
|
||||||
|
|
||||||
## Translating
|
## Translating
|
||||||
@ -56,8 +91,15 @@ position data (just edit the `src/constants.js` file accordingly).
|
|||||||
Translation is done directly on [Zanata](https://translate.zanata.org/iteration/view/cyclassist/master?dswid=7345).
|
Translation is done directly on [Zanata](https://translate.zanata.org/iteration/view/cyclassist/master?dswid=7345).
|
||||||
|
|
||||||
To add new strings to localize, edit the `src/i18n/en.json` file with your new
|
To add new strings to localize, edit the `src/i18n/en.json` file with your new
|
||||||
strings (and only this file). Then, you can run `yarn push-locales` to send
|
strings (and only this file). English locale should be considered as the
|
||||||
the updated locales to translate and `yarn pull-locales` to fetch the
|
reference locale and new strings should always be added there.
|
||||||
translated files. To use these scripts you will need the
|
|
||||||
Translate-toolkit(`pip install translate-toolkit`) and the [Zanata Python CLI
|
Then, you can run `yarn push-locales` to send the updated locales to translate
|
||||||
|
to the Zanata server.
|
||||||
|
|
||||||
|
Once the strings have been translated at Zanata, you can run `yarn
|
||||||
|
pull-locales` to fetch the translated files.
|
||||||
|
|
||||||
|
_Note :_ To use these scripts you will need the Translate-toolkit(`pip install
|
||||||
|
translate-toolkit`) and the [Zanata Python CLI
|
||||||
client](https://github.com/zanata/zanata-python-client).
|
client](https://github.com/zanata/zanata-python-client).
|
||||||
|
116
README.md
116
README.md
@ -10,8 +10,8 @@ serve the issues. This code is the code running behind https://cyclo.phyks.me/
|
|||||||
|
|
||||||
**A sandbox instance if you want to try it out without polluting the main instance
|
**A sandbox instance if you want to try it out without polluting the main instance
|
||||||
is available at https://cyclo-dev.phyks.me**. Please note however this is a
|
is available at https://cyclo-dev.phyks.me**. Please note however this is a
|
||||||
sandbox instance which might be ahead of the official https://cyclo.phyks.me
|
development instance which might be ahead of the official https://cyclo.phyks.me
|
||||||
instance from time to time, so that it might break from time to time.
|
instance from time to time. It might break from time to time.
|
||||||
|
|
||||||
As of current version, only the client side part (code running on your local
|
As of current version, only the client side part (code running on your local
|
||||||
device) handles your geolocation. **Your precise geolocation is never sent**
|
device) handles your geolocation. **Your precise geolocation is never sent**
|
||||||
@ -21,6 +21,7 @@ could know the location of the displayed map.
|
|||||||
|
|
||||||
<img src="support/screenshots/webapp.jpg" width="45%"/> <img src="support/screenshots/reportDialog.jpg" width="45%"/>
|
<img src="support/screenshots/webapp.jpg" width="45%"/> <img src="support/screenshots/reportDialog.jpg" width="45%"/>
|
||||||
|
|
||||||
|
|
||||||
## OpenData
|
## OpenData
|
||||||
|
|
||||||
The data collected by https://cyclo.phyks.me/ is available under an
|
The data collected by https://cyclo.phyks.me/ is available under an
|
||||||
@ -31,119 +32,18 @@ https://cyclo.phyks.me/api/v1/reports.
|
|||||||
Statistics about the instance can be fetched at
|
Statistics about the instance can be fetched at
|
||||||
https://cyclo.phyks.me/api/v1/stats.
|
https://cyclo.phyks.me/api/v1/stats.
|
||||||
|
|
||||||
## Hosting your own
|
|
||||||
|
|
||||||
### Client part
|
## Documentation
|
||||||
|
|
||||||
#### Build setup
|
Detailed documentation about this software is available under the
|
||||||
|
[`doc/`](doc/) folder. This covers setting up your own instance, API, privacy
|
||||||
``` bash
|
choices etc.
|
||||||
# Install JS dependencies
|
|
||||||
yarn install
|
|
||||||
|
|
||||||
# Serve with hot reload at localhost:8080
|
|
||||||
yarn dev
|
|
||||||
|
|
||||||
# Build for production with minification
|
|
||||||
yarn build
|
|
||||||
|
|
||||||
# Build for production and view the bundle analyzer report
|
|
||||||
yarn build --report
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Useful environment variables
|
|
||||||
|
|
||||||
You can pass a few environment variables to the `yarn build|dev` commands to
|
|
||||||
adapt the behavior to your needs.
|
|
||||||
|
|
||||||
* `PUBLIC_PATH=https://.../foobar` to serve the app from a subdirectory.
|
|
||||||
* `API_BASE_URL=https://...` to specify the location of the server (defaults
|
|
||||||
to `/`). The value should end with a trailing slash.
|
|
||||||
* `THUNDERFOREST_API_KEY=` to pass an API key server to use for
|
|
||||||
[Thunderforest](http://thunderforest.com/) tiles (OpenCycleMap, etc).
|
|
||||||
* `API_TOKEN=` to pass a token required to access the server side API (check
|
|
||||||
below in the server part environment variables for more details).
|
|
||||||
|
|
||||||
You should also have a look at the build variables under the `config/`
|
|
||||||
subdirectory.
|
|
||||||
|
|
||||||
|
|
||||||
#### Geographical extension
|
|
||||||
|
|
||||||
While the frontend could theoretically work in the entire world without much
|
|
||||||
modifications, it is currently written with mainland France in mind, mostly
|
|
||||||
because that is the territory the authors are most familiar with.
|
|
||||||
Additionnally, this limits the volume of geographical data (such as OSM
|
|
||||||
extracts) to handle and makes managing the app easier.
|
|
||||||
|
|
||||||
You could of course easily extend it to support other territories. The
|
|
||||||
French-specific parts of the code so far are:
|
|
||||||
* The [`AddressInput`](https://framagit.org/phyks/cyclassist/blob/master/src/components/AddressInput.vue) component which uses the [https://adresse.data.gouv.fr/](https://adresse.data.gouv.fr/) API to autocomplete addresses. You could easily replace it with [Algolia Places](https://community.algolia.com/places/) which covers the entire world.
|
|
||||||
|
|
||||||
|
|
||||||
#### Notes
|
|
||||||
|
|
||||||
We are using [A la carte](https://vuetifyjs.com/en/guides/a-la-carte) Vuetify
|
|
||||||
components to reduce the size of the build. Check that any extra components
|
|
||||||
you might use is indeed included in `src/vuetify.js` file. The `yarn
|
|
||||||
list-vuetify-components` command might be useful to help you determine which
|
|
||||||
components are used across the code.
|
|
||||||
|
|
||||||
|
|
||||||
### Server part
|
|
||||||
|
|
||||||
#### Build setup
|
|
||||||
|
|
||||||
``` bash
|
|
||||||
# Install Python dependencies
|
|
||||||
pip install -r requirements.txt
|
|
||||||
|
|
||||||
# Start the server
|
|
||||||
python -m server
|
|
||||||
```
|
|
||||||
|
|
||||||
It is better to use a dedicated `virtualenv` if you can :)
|
|
||||||
|
|
||||||
API routes are all listed within `server/routes.py` file, with documentation
|
|
||||||
strings.
|
|
||||||
|
|
||||||
#### Useful environment variables
|
|
||||||
|
|
||||||
You can pass a few environment variables to the `python -m server` command to
|
|
||||||
adapt its behavior:
|
|
||||||
|
|
||||||
* `HOST=` to specify the host to listen to (defaults to `127.0.0.1` which
|
|
||||||
means `localhost` only).
|
|
||||||
* `PORT=` to specify the port to listen on (defaults to `8081`).
|
|
||||||
* `DATABASE=` to specify a [database URL](http://docs.peewee-orm.com/en/latest/peewee/playhouse.html#db-url) to connect to (defaults to
|
|
||||||
`sqlite:///reports.db` which means a SQLite database named `reports.db` in
|
|
||||||
the current working directory).
|
|
||||||
* `API_TOKEN=` to specify a token required to `POST` data to the API.
|
|
||||||
|
|
||||||
#### Serving in production
|
|
||||||
|
|
||||||
You can use the `wsgi.py` script at the root of the git repository to serve
|
|
||||||
the server side part. You can find some `uwsgi` and `nginx` base config files
|
|
||||||
under the `support` folder.
|
|
||||||
|
|
||||||
#### Importing OpenData
|
|
||||||
|
|
||||||
A few OpenData files can be imported in Cycl'Assist, to import roadworks for
|
|
||||||
instance. All the useful scripts to import OpenData are in the
|
|
||||||
`scripts/opendata` folder. You can set up a daily cron task to automatically
|
|
||||||
run the import of roadworks every day.
|
|
||||||
|
|
||||||
#### Updating
|
|
||||||
|
|
||||||
Database migrations are in the `scripts/migrations` folder, labelled by
|
|
||||||
versions. You should run them in order from your current versions to the
|
|
||||||
latest one when you upgrade.
|
|
||||||
|
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
Check out the [CONTRIBUTING.md](CONTRIBUTING.md) file for all the required doc
|
Check out the [CONTRIBUTING.md](CONTRIBUTING.md) file for all the required doc
|
||||||
and details before contributing :) Any contributions more than welcome!
|
and details before contributing :) Any contributions are more than welcome!
|
||||||
|
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
146
doc/0.hosting.md
Normal file
146
doc/0.hosting.md
Normal file
@ -0,0 +1,146 @@
|
|||||||
|
Hosting your own
|
||||||
|
================
|
||||||
|
|
||||||
|
The app is made of two separate parts. A (micro-)server part which is
|
||||||
|
basically just exposing an API on top of the database and a client part
|
||||||
|
(static JS scripts and assets) which is accessing this API.
|
||||||
|
|
||||||
|
## Updating the app
|
||||||
|
|
||||||
|
Whenever new versions are published, here is a quick guide to do the upgrade:
|
||||||
|
|
||||||
|
* fetch the last updated files from the repository
|
||||||
|
* ensure the client part build is up to date
|
||||||
|
(`yarn install && yarn build`)
|
||||||
|
* check for required migrations (see below)
|
||||||
|
* ensure the server part requirements are up to date (`pip install -r
|
||||||
|
requirements.txt`) and restart the server
|
||||||
|
|
||||||
|
From times to times, the database schema might need to be updated. Migrations
|
||||||
|
(scripts to edit the database schema for you) are provided under the
|
||||||
|
`scripts/migrations` folder. The scripts in this folder are labelled by
|
||||||
|
versions, meaning that the `0.3.py` script handles the migration of the
|
||||||
|
database from the version immediately before `0.3` to the `0.3` version of the
|
||||||
|
app.
|
||||||
|
|
||||||
|
If you upgrade through several versions at once, you should run all the
|
||||||
|
migrations scripts for all the intermediate versions, in the ascending order.
|
||||||
|
There are currently no automated way to handle the updates of the database
|
||||||
|
schema.
|
||||||
|
|
||||||
|
_Note :_ Versions of the app are listed in the git tags. Current version of
|
||||||
|
the code is also in the `src/constants.js` file.
|
||||||
|
|
||||||
|
|
||||||
|
## Server part
|
||||||
|
|
||||||
|
### Build setup
|
||||||
|
|
||||||
|
``` bash
|
||||||
|
# Install Python dependencies
|
||||||
|
pip install -r requirements.txt
|
||||||
|
|
||||||
|
# Start the server
|
||||||
|
python -m server
|
||||||
|
```
|
||||||
|
|
||||||
|
It is better to use a dedicated `virtualenv` if you can, to help manage Python
|
||||||
|
dependencies in a clean way.
|
||||||
|
|
||||||
|
API routes are all listed within `server/routes.py` file, with documentation
|
||||||
|
strings.
|
||||||
|
|
||||||
|
### Useful environment variables
|
||||||
|
|
||||||
|
You can pass a few environment variables to the `python -m server` command to
|
||||||
|
adapt its behavior:
|
||||||
|
|
||||||
|
* `HOST=` to specify the host to listen to (defaults to `127.0.0.1` which
|
||||||
|
means `localhost` only).
|
||||||
|
* `PORT=` to specify the port to listen on (defaults to `8081`).
|
||||||
|
* `DATABASE=` to specify a [database URL](http://docs.peewee-orm.com/en/latest/peewee/playhouse.html#db-url) to connect to (defaults to
|
||||||
|
`sqlite:///reports.db` which means a SQLite database named `reports.db` in
|
||||||
|
the current working directory).
|
||||||
|
* `API_TOKEN=` to specify a token required to `POST` data to the API.
|
||||||
|
|
||||||
|
### Serving in production
|
||||||
|
|
||||||
|
You can use the `wsgi.py` script at the root of the git repository to serve
|
||||||
|
the server side part. You can find some `uwsgi` and `nginx` base config files
|
||||||
|
under the `support` folder.
|
||||||
|
|
||||||
|
You might also want to put some rate-limiting in front of the API. This can be
|
||||||
|
done easily when you use `nginx` as a reverse proxy for instance. This is
|
||||||
|
handled by the `limit_req` directive in the `nginx` base config files provided
|
||||||
|
in the `support` folder. You can then edit the
|
||||||
|
`DELAY_BETWEEN_API_BATCH_REQUESTS` configuration option in `src/constants.js`
|
||||||
|
to ensure that requests will be spaced enough when sending a batch of them so
|
||||||
|
that they will not be blocked by your rate-limiting.
|
||||||
|
|
||||||
|
### Importing OpenData
|
||||||
|
|
||||||
|
A few OpenData files can be imported in Cycl'Assist, to import roadworks for
|
||||||
|
instance. All the useful scripts to import OpenData are in the
|
||||||
|
`scripts/opendata` folder.
|
||||||
|
|
||||||
|
You can set up a daily cron task to automatically run the import of opendata
|
||||||
|
every day for instance.
|
||||||
|
|
||||||
|
|
||||||
|
## Client part
|
||||||
|
|
||||||
|
### Build setup
|
||||||
|
|
||||||
|
Here are the steps to build the client side assets and scripts.
|
||||||
|
|
||||||
|
``` bash
|
||||||
|
# Install JS dependencies
|
||||||
|
yarn install
|
||||||
|
|
||||||
|
# Serve with hot reload at localhost:8080
|
||||||
|
# (For development only)
|
||||||
|
yarn dev
|
||||||
|
|
||||||
|
# Build for production with minification
|
||||||
|
# Output assets and scripts in the `dist/` folder, ready to be used in
|
||||||
|
# production.
|
||||||
|
yarn build
|
||||||
|
|
||||||
|
# Build for production and view the bundle analyzer report
|
||||||
|
# (might be useful for debugging or development)
|
||||||
|
yarn build --report
|
||||||
|
```
|
||||||
|
|
||||||
|
To serve the app in production, you have to build the scripts and assets using
|
||||||
|
`yarn build`. It will output everything under the `dist/` folder which you can
|
||||||
|
then serve using any web server (these are just static files to be served).
|
||||||
|
|
||||||
|
|
||||||
|
### Useful environment variables
|
||||||
|
|
||||||
|
You can pass a few environment variables to the `yarn build|dev` commands to
|
||||||
|
adapt the behavior to your needs.
|
||||||
|
|
||||||
|
* `PUBLIC_PATH=https://.../foobar` to serve the app from a subdirectory.
|
||||||
|
* `API_BASE_URL=https://...` to specify the location of the server API (defaults
|
||||||
|
to `/`). The value should end with a trailing slash.
|
||||||
|
* `THUNDERFOREST_API_KEY=` to pass an API key server to use for
|
||||||
|
[Thunderforest](http://thunderforest.com/) tiles (OpenCycleMap, etc).
|
||||||
|
* `API_TOKEN=` to pass a token required to access the server side API (check
|
||||||
|
below in the server part environment variables for more details).
|
||||||
|
|
||||||
|
You should also have a look at the build variables under the `config/`
|
||||||
|
subdirectory.
|
||||||
|
|
||||||
|
|
||||||
|
### Geographical extension
|
||||||
|
|
||||||
|
While the frontend could theoretically work in the entire world without much
|
||||||
|
modifications, it is currently written with mainland France in mind, mostly
|
||||||
|
because that is the territory the authors are most familiar with.
|
||||||
|
Additionnally, this limits the volume of geographical data (such as OSM
|
||||||
|
extracts) to handle and makes managing the app easier.
|
||||||
|
|
||||||
|
You could of course easily extend it to support other territories. The
|
||||||
|
French-specific parts of the code so far are:
|
||||||
|
* The [`AddressInput`](https://framagit.org/phyks/cyclassist/blob/master/src/components/AddressInput.vue) component which uses the [https://adresse.data.gouv.fr/](https://adresse.data.gouv.fr/) API to autocomplete addresses. You could easily replace it with [Algolia Places](https://community.algolia.com/places/) which covers the entire world.
|
26
doc/10.technical_notes.md
Normal file
26
doc/10.technical_notes.md
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
Technical notes
|
||||||
|
===============
|
||||||
|
|
||||||
|
## Privacy design
|
||||||
|
|
||||||
|
The software was built with the idea that your location should only be handled
|
||||||
|
in the client part. Then, it should never be sent to the server part or any
|
||||||
|
third party without your knowledge. The app should also provide as much
|
||||||
|
features as possible without even knowing your location (in case you disabled
|
||||||
|
geolocation on your device).
|
||||||
|
|
||||||
|
If geolocation is turned off, it falls back to asking you to manually enter a
|
||||||
|
location through a text field. Of course, without geolocation tracking, some
|
||||||
|
features no longer makes sense, but you can still browse the reports and
|
||||||
|
manually add reports at specific known locations.
|
||||||
|
|
||||||
|
If geolocation is turned on, your geolocation data is only handled locally, on
|
||||||
|
your device. This means that your precise location is never sent to the
|
||||||
|
server. When fetching reports nearby, all the valid reports from the
|
||||||
|
server are downloaded and the filtering is done client-side, to avoid sharing
|
||||||
|
your precise geolocation with the server.
|
||||||
|
|
||||||
|
*Note:* The map tiles (the map background) is downloaded from third
|
||||||
|
party servers and due to the very nature of the images, it could leak hints
|
||||||
|
about your geolocation. This might be something addressed in the future by
|
||||||
|
letting you batch download a given area in advance.
|
10
doc/20.api.md
Normal file
10
doc/20.api.md
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
API
|
||||||
|
===
|
||||||
|
|
||||||
|
The server part exposes a public API (by default). Read from the API is always
|
||||||
|
public but writing new reports can be restricted through the use of an
|
||||||
|
API token (see the doc about deployment for more infos).
|
||||||
|
|
||||||
|
A helper script is available under `scripts/api_doc.py` to export a
|
||||||
|
documentation of the available API endpoints and usage in the current version
|
||||||
|
of the code.
|
20
scripts/api_doc.py
Executable file
20
scripts/api_doc.py
Executable file
@ -0,0 +1,20 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
import bottle
|
||||||
|
|
||||||
|
SCRIPT_DIRECTORY = os.path.dirname(os.path.realpath(__file__))
|
||||||
|
sys.path.append(os.path.abspath(os.path.join(SCRIPT_DIRECTORY, '..')))
|
||||||
|
|
||||||
|
import server.routes
|
||||||
|
|
||||||
|
app_routes = [x for x in bottle.default_app().routes]
|
||||||
|
for route in app_routes:
|
||||||
|
if route.method == "OPTIONS":
|
||||||
|
# Ignore CORS handling
|
||||||
|
continue
|
||||||
|
print(route.rule)
|
||||||
|
print(''.join('=' for _ in route.rule))
|
||||||
|
print(route.callback.__doc__)
|
||||||
|
print('')
|
134
server/routes.py
134
server/routes.py
@ -102,7 +102,28 @@ def get_all_reports():
|
|||||||
|
|
||||||
Example::
|
Example::
|
||||||
|
|
||||||
GET /api/v1/reports
|
> GET /api/v1/reports
|
||||||
|
|
||||||
|
{
|
||||||
|
"data": [
|
||||||
|
{
|
||||||
|
"attributes": {
|
||||||
|
"expiration_datetime": null,
|
||||||
|
"downvotes": 0,
|
||||||
|
"datetime": "2018-06-27T16:44:12+00:00",
|
||||||
|
"is_open": true,
|
||||||
|
"lat": 48.842005,
|
||||||
|
"upvotes": 1,
|
||||||
|
"lng": 2.386278,
|
||||||
|
"type": "interrupt",
|
||||||
|
…
|
||||||
|
},
|
||||||
|
"type": "reports",
|
||||||
|
"id": 1
|
||||||
|
},
|
||||||
|
…
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
@ -134,7 +155,28 @@ def get_active_reports():
|
|||||||
|
|
||||||
Example::
|
Example::
|
||||||
|
|
||||||
GET /api/v1/reports/active
|
> GET /api/v1/reports/active
|
||||||
|
|
||||||
|
{
|
||||||
|
"data": [
|
||||||
|
{
|
||||||
|
"attributes": {
|
||||||
|
"expiration_datetime": null,
|
||||||
|
"downvotes": 0,
|
||||||
|
"datetime": "2018-06-27T16:44:12+00:00",
|
||||||
|
"is_open": true,
|
||||||
|
"lat": 48.842005,
|
||||||
|
"upvotes": 1,
|
||||||
|
"lng": 2.386278,
|
||||||
|
"type": "interrupt",
|
||||||
|
…
|
||||||
|
},
|
||||||
|
"type": "reports",
|
||||||
|
"id": 1
|
||||||
|
},
|
||||||
|
…
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
@ -165,12 +207,33 @@ def post_report():
|
|||||||
|
|
||||||
Example::
|
Example::
|
||||||
|
|
||||||
POST /api/v1/reports
|
> POST /api/v1/reports
|
||||||
|
> {
|
||||||
|
> "type": "pothole",
|
||||||
|
> "lat": 48.84219652060494,
|
||||||
|
> "lng": 2.385234797066081
|
||||||
|
> }
|
||||||
|
|
||||||
{
|
{
|
||||||
"type": "toto",
|
"data": {
|
||||||
"lat": 32,
|
"attributes": {
|
||||||
"lng": 27
|
"expiration_datetime": null,
|
||||||
|
"downvotes": 0,
|
||||||
|
"datetime": "2018-10-17T13:42:35+00:00",
|
||||||
|
"first_report_datetime": "2018-10-17T13:42:35+00:00",
|
||||||
|
"lat": 48.84219652060494,
|
||||||
|
"upvotes": 0,
|
||||||
|
"lng": 2.385234797066081,
|
||||||
|
"type": "pothole",
|
||||||
|
"is_open": true,
|
||||||
|
…
|
||||||
|
},
|
||||||
|
"type": "reports",
|
||||||
|
"id": 1161
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:return: The newly created report object in a JSON ``data`` dict.
|
||||||
"""
|
"""
|
||||||
# Handle CORS
|
# Handle CORS
|
||||||
if bottle.request.method == 'OPTIONS':
|
if bottle.request.method == 'OPTIONS':
|
||||||
@ -214,7 +277,28 @@ def upvote_report(id):
|
|||||||
|
|
||||||
Example::
|
Example::
|
||||||
|
|
||||||
POST /api/v1/reports/1/upvote
|
> POST /api/v1/reports/1/upvote
|
||||||
|
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"attributes": {
|
||||||
|
"expiration_datetime": null,
|
||||||
|
"downvotes": 0,
|
||||||
|
"datetime": "2018-10-17T13:42:35+00:00",
|
||||||
|
"first_report_datetime": "2018-10-17T13:42:35+00:00",
|
||||||
|
"lat": 48.84219652060494,
|
||||||
|
"upvotes": 1,
|
||||||
|
"lng": 2.385234797066081,
|
||||||
|
"type": "pothole",
|
||||||
|
"is_open": true,
|
||||||
|
…
|
||||||
|
},
|
||||||
|
"type": "reports",
|
||||||
|
"id": 1161
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
:return: The updated report object in a JSON ``data`` dict.
|
||||||
"""
|
"""
|
||||||
# Handle CORS
|
# Handle CORS
|
||||||
if bottle.request.method == 'OPTIONS':
|
if bottle.request.method == 'OPTIONS':
|
||||||
@ -252,7 +336,28 @@ def downvote_report(id):
|
|||||||
|
|
||||||
Example::
|
Example::
|
||||||
|
|
||||||
POST /api/v1/reports/1/downvote
|
> POST /api/v1/reports/1/downvote
|
||||||
|
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"attributes": {
|
||||||
|
"expiration_datetime": null,
|
||||||
|
"downvotes": 1,
|
||||||
|
"datetime": "2018-10-17T13:42:35+00:00",
|
||||||
|
"first_report_datetime": "2018-10-17T13:42:35+00:00",
|
||||||
|
"lat": 48.84219652060494,
|
||||||
|
"upvotes": 0,
|
||||||
|
"lng": 2.385234797066081,
|
||||||
|
"type": "pothole",
|
||||||
|
"is_open": true,
|
||||||
|
…
|
||||||
|
},
|
||||||
|
"type": "reports",
|
||||||
|
"id": 1161
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
:return: The updated report object in a JSON ``data`` dict.
|
||||||
"""
|
"""
|
||||||
# Handle CORS
|
# Handle CORS
|
||||||
if bottle.request.method == 'OPTIONS':
|
if bottle.request.method == 'OPTIONS':
|
||||||
@ -282,7 +387,18 @@ def get_stats():
|
|||||||
|
|
||||||
Example::
|
Example::
|
||||||
|
|
||||||
GET /api/v1/states
|
> GET /api/v1/stats
|
||||||
|
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"nb_active_reports": 606,
|
||||||
|
"nb_reports": 1162,
|
||||||
|
"last_added_report_datetime": "2018-10-17T13:44:16+00:00",
|
||||||
|
…
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
:return: The available stats about the instance in a JSON ``data`` dict.
|
||||||
"""
|
"""
|
||||||
# Handle CORS
|
# Handle CORS
|
||||||
if bottle.request.method == 'OPTIONS':
|
if bottle.request.method == 'OPTIONS':
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
# API rate limitation
|
# Define API rate limitation
|
||||||
limit_req_zone $binary_remote_addr zone=cycloAPI:10m rate=1r/s;# UWSGI proxy pass
|
limit_req_zone $binary_remote_addr zone=cycloAPI:10m rate=1r/s;# UWSGI proxy pass
|
||||||
|
|
||||||
|
# Define the server to use upstream, here we assume we serve Cyclassist using
|
||||||
|
# UWSGI.
|
||||||
upstream _cyclassist {
|
upstream _cyclassist {
|
||||||
server unix:/run/uwsgi/app/cyclassist/socket;
|
server unix:/run/uwsgi/app/cyclassist/socket;
|
||||||
}
|
}
|
||||||
|
|
||||||
# Expires map
|
# Expires map, to ensure correct caching of the assets.
|
||||||
map $sent_http_content_type $expires {
|
map $sent_http_content_type $expires {
|
||||||
default off;
|
default off;
|
||||||
text/html epoch;
|
text/html epoch;
|
||||||
@ -46,7 +48,7 @@ server {
|
|||||||
|
|
||||||
# Proxy pass the API calls to the server part
|
# Proxy pass the API calls to the server part
|
||||||
location /api {
|
location /api {
|
||||||
limit_req zone=cycloAPI burst=3 nodelay;
|
limit_req zone=cycloAPI burst=3 nodelay; # Add rate-limiting on top of the API
|
||||||
include uwsgi_params;
|
include uwsgi_params;
|
||||||
uwsgi_pass _cyclassist;
|
uwsgi_pass _cyclassist;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user