mybuddy/README.md

583 lines
18 KiB
Markdown
Raw Normal View History

2018-04-17 13:19:06 +00:00
<img src="babybuddy/static_src/logo/icon.png" height="150" align="left">
2018-04-16 12:45:23 +00:00
2017-10-22 20:00:29 +00:00
# Baby Buddy
[![License](https://img.shields.io/badge/License-BSD%202--Clause-orange.svg)](https://opensource.org/licenses/BSD-2-Clause)
[![Gitter](https://img.shields.io/gitter/room/nwjs/nw.js.svg)](https://gitter.im/babybuddy/Lobby)
2020-01-19 16:49:45 +00:00
A buddy for babies! Helps caregivers track sleep, feedings, diaper changes,
tummy time and more to learn about and predict baby's needs without (*as much*)
guess work.
![Baby Buddy desktop view](screenshot.png)
![Baby Buddy mobile views](screenshot_mobile.png)
2017-10-22 20:00:29 +00:00
2017-11-15 18:08:13 +00:00
**Table of Contents**
- [Demo](#demo)
- [Deployment](#deployment)
- [AWS Elastic Beanstalk](#aws-elastic-beanstalk)
- [Docker](#docker)
- [Heroku](#heroku)
2017-11-20 16:12:09 +00:00
- [Manual](#manual)
- [Configuration](#configuration)
2019-05-04 13:05:36 +00:00
- [Languages](#languages)
- [Import/Export](#importexport)
- [Export](#export)
- [Import](#import)
2017-12-05 21:46:15 +00:00
- [API](#api)
- [Authentication](#authentication)
2017-12-06 00:43:57 +00:00
- [`GET` Method](#get-method)
- [`OPTIONS` Method](#options-method)
- [`POST` Method](#post-method)
- [Contributing](#contributing)
2017-11-15 18:08:13 +00:00
2017-10-23 09:25:56 +00:00
## Demo
2017-11-30 00:28:43 +00:00
A [demo of Baby Buddy](http://demo.baby-buddy.net) is available on Heroku.
The demo instance resets every hour. Login credentials are:
- Username: `admin`
- Password: `admin`
2017-10-23 09:25:56 +00:00
2017-10-24 00:33:28 +00:00
## Deployment
The default user name and password for Baby Buddy is `admin`/`admin`. For any
2017-11-30 00:28:43 +00:00
deployment, **log in and change the default admin password immediately**.
Many of Baby Buddy's configuration settings can be controlled using environment
variables - see [Configuration](#configuration) for detailed information.
2017-11-15 18:08:13 +00:00
### AWS Elastic Beanstalk
2017-10-24 00:33:28 +00:00
A basic [Elastic Beanstalk](https://aws.amazon.com/elasticbeanstalk/)
configuration is provided in `.ebextensions/babybuddy.config`. The steps
2020-01-19 16:49:45 +00:00
below are a rough guide to deployment. See [Working with Python](https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/create-deploy-python-apps.html)
for detailed information.
2017-10-24 00:33:28 +00:00
1. Clone/download the Baby Buddy repo
2017-11-15 18:08:13 +00:00
2020-02-07 06:16:57 +00:00
git clone https://github.com/babybuddy/babybuddy.git
1. Enter the cloned/downloaded directory
cd babybuddy
1. Set (at least) the `SECRET_KEY` environment value in `.ebextensions/babybuddy.config`
*See [Configuration](#configuration) for other settings that can be
controlled by environment variables.
1. [Create an IAM user](http://docs.aws.amazon.com/IAM/latest/UserGuide/id_users_create.html) in AWS with EB, EC2, RDS and S3 privileges.
1. Initialize the Elastic Bean application (using the IAM user from the previous step)
eb init -p python-3.6
1. Create/deploy the environment! :rocket:
eb create -db -db.engine postgres
The create command will also do an initial deployment. Run `eb deploy` to
redeploy the app (e.g. if there are errors or settings are changed).
2017-11-15 18:08:13 +00:00
### Docker
A Docker deployment requires [Docker Engine](https://www.docker.com/) v18.06.0+
and [Docker Compose](https://docs.docker.com/compose/) v1.22.0+ to create two
containers: one for the database and one for the application.
2017-12-01 03:33:51 +00:00
The example `docker-compose.example.yml` file provided in this repository is
intended for production deployments. Baby Buddy is deployed to Docker Hub as
2020-02-07 19:55:36 +00:00
[babybuddy/babybuddy](https://hub.docker.com/r/babybuddy/babybuddy) so this is
the only file needed for a Docker deployment with Docker Compose.
1. Copy the contents of `docker-compose.example.yml` as `docker-compose.yml`
and set, at least, the `ALLOWED_HOSTS` and `SECRET_KEY` variables under
`services:app:environment`.
*See [Configuration](#configuration) for other settings that can be
controlled by environment variables.*
1. Build/run the application
docker-compose up -d
1. Initialize the database *(first run/after migrations updates)*
docker-compose exec app python manage.py migrate
1. Initialize cache table *(first run/after cache configuration updates)*
docker-compose exec app python manage.py createcachetable
The app should now be locally available at
[http://127.0.0.1:8000](http://127.0.0.1:8000). See
2020-01-19 16:49:45 +00:00
[Docker's "Get Started" documentation](https://docs.docker.com/get-started/)
for detailed information about deployment methods with Docker.
### Heroku
[![Deploy](https://www.herokucdn.com/deploy/button.svg)](https://heroku.com/deploy)
For manual deployments to Heroku without using the deploy button, make sure to
create the following settings before pushing:
heroku config:set DJANGO_SETTINGS_MODULE=babybuddy.settings.heroku
heroku config:set SECRET_KEY=<CHANGE TO SOMETHING RANDOM>
heroku config:set DISABLE_COLLECTSTATIC=1
heroku config:set TIME_ZONE=<DESIRED DEFAULT TIMEZONE>
See [Configuration](#configuration) for other settings that can be controlled
2017-11-30 00:28:43 +00:00
by `heroku config:set`.
2020-01-31 04:46:23 +00:00
And after an initial push, execute the following commands:
heroku run python manage.py migrate
heroku run python manage.py createcachetable
2017-11-20 16:12:09 +00:00
### Manual
2018-10-21 15:19:57 +00:00
There are many ways to deploy Baby Buddy manually to any server/VPS. The basic
requirements are Python, a web server, an application server, and a database.
2017-11-20 16:12:09 +00:00
#### Requirements
- Python 3.6+, pip, pipenv
2017-11-20 16:12:09 +00:00
- Web server ([nginx](http://nginx.org/), [Apache](http://httpd.apache.org/), etc.)
- Application server ([uwsgi](http://projects.unbit.it/uwsgi), [gunicorn](http://gunicorn.org/), etc.)
- Database ([sqlite](https://sqlite.org/), [Postgres](https://www.postgresql.org/), [MySQL](https://www.mysql.com/), etc.)
#### Example deployment
*This example assumes a 512MB VPS instance with Ubuntu 18.04.* It uses
Python 3.6+, nginx, uwsgi and sqlite and should be sufficient for a few users
2017-11-20 16:12:09 +00:00
(e.g. two parents and 1+ child).
2018-10-21 15:19:57 +00:00
1. Install system packages
2017-11-20 16:12:09 +00:00
2018-05-08 04:54:21 +00:00
sudo apt-get install python3 python3-pip nginx uwsgi uwsgi-plugin-python3 git libopenjp2-7-dev
2017-11-20 16:12:09 +00:00
2018-05-05 19:29:02 +00:00
1. Default python3 to python for this session
2018-05-04 09:20:31 +00:00
alias python=python3
2017-11-20 16:12:09 +00:00
1. Install pipenv
sudo -H pip3 install pipenv
2017-11-20 16:12:09 +00:00
1. Set up directories and files
sudo mkdir /var/www/babybuddy
sudo chown user:user /var/www/babybuddy
mkdir -p /var/www/babybuddy/data/media
2020-02-07 06:16:57 +00:00
git clone https://github.com/babybuddy/babybuddy.git /var/www/babybuddy/public
2017-11-20 16:12:09 +00:00
1. Move in to the application folder
cd /var/www/babybuddy/public
1. Set pipenv to install locally.
export PIPENV_VENV_IN_PROJECT=1
2017-11-20 16:12:09 +00:00
2018-10-21 15:19:57 +00:00
1. Initiate and enter the Python environment
2017-11-20 16:12:09 +00:00
2018-10-21 15:19:57 +00:00
pipenv install --three
pipenv shell
**Note:** Python dependencies are locked on x86-64 architecture. Installs
on other architectures (like Raspberry Pi's ARM) may result in a
``THESE PACKAGES DO NOT MATCH THE HASHES FROM Pipfile.lock!`` error. Add
the ``--skip-lock`` flag to the above command to suppress this error
(i.e.: ``pipenv install --three --dev --skip-lock``).
2017-11-20 16:12:09 +00:00
1. Create a production settings file and set the ``SECRET_KEY`` and ``ALLOWED_HOSTS`` values
cp babybuddy/settings/production.example.py babybuddy/settings/production.py
editor babybuddy/settings/production.py
1. Initiate the application
export DJANGO_SETTINGS_MODULE=babybuddy.settings.production
2018-10-21 15:19:57 +00:00
python manage.py migrate
python manage.py createcachetable
2017-11-20 16:12:09 +00:00
1. Set appropriate permissions on the database and data folder
sudo chown -R www-data:www-data /var/www/babybuddy/data
2017-11-20 16:12:09 +00:00
sudo chmod 640 /var/www/babybuddy/data/db.sqlite3
sudo chmod 750 /var/www/babybuddy/data
1. Create and configure the uwsgi app
sudo editor /etc/uwsgi/apps-available/babybuddy.ini
2017-11-20 16:12:09 +00:00
Example config:
2017-11-20 16:12:09 +00:00
[uwsgi]
plugins = python3
project = babybuddy
base_dir = /var/www/babybuddy
chdir = %(base_dir)/public
virtualenv = %(chdir)/.venv
2017-11-20 16:12:09 +00:00
module = %(project).wsgi:application
env = DJANGO_SETTINGS_MODULE=%(project).settings.production
master = True
vacuum = True
See the [uWSGI documentation](http://uwsgi-docs.readthedocs.io/en/latest/)
2017-11-20 16:12:09 +00:00
for more advanced configuration details.
2018-05-08 04:50:55 +00:00
1. Symlink config and restart uWSGI:
2018-05-07 21:02:03 +00:00
sudo ln -s /etc/uwsgi/apps-available/babybuddy.ini /etc/uwsgi/apps-enabled/babybuddy.ini
sudo service uwsgi restart
2017-11-20 16:12:09 +00:00
1. Create and configure the nginx server
sudo editor /etc/nginx/sites-available/babybuddy
2017-11-20 16:12:09 +00:00
Example config:
upstream babybuddy {
server unix:///var/run/uwsgi/app/babybuddy/socket;
}
2017-11-20 16:12:09 +00:00
server {
listen 80;
server_name babybuddy.example.com;
2017-11-20 16:12:09 +00:00
location / {
uwsgi_pass babybuddy;
include uwsgi_params;
}
2018-10-21 15:19:57 +00:00
location /media {
alias /var/www/babybuddy/data/media;
}
2017-11-20 16:12:09 +00:00
}
See the [nginx documentation](https://nginx.org/en/docs/) for more advanced
configuration details.
2018-05-08 04:51:26 +00:00
1. Symlink config and restart NGINX:
sudo ln -s /etc/nginx/sites-available/babybuddy /etc/nginx/sites-enabled/babybuddy
sudo service nginx restart
2017-11-20 16:12:09 +00:00
1. That's it (hopefully)! :tada:
## Configuration
Environment variables can be used to define a number of configuration settings.
Baby Buddy will check the application directory structure for an `.env` file or
take these variables from the system environment. **System environment variables
take precedence over the contents of an `.env` file.**
- [`ALLOWED_HOSTS`](#allowed_hosts)
- [`ALLOW_UPLOADS`](#allow_uploads)
- [`AWS_ACCESS_KEY_ID`](#aws_access_key_id)
- [`AWS_SECRET_ACCESS_KEY`](#aws_secret_access_key)
- [`AWS_STORAGE_BUCKET_NAME`](#aws_storage_bucket_name)
- [`DEBUG`](#debug)
- [`NAP_START_MAX`](#nap_start_max)
- [`NAP_START_MIN`](#nap_start_min)
- [`SECRET_KEY`](#secret_key)
- [`TIME_ZONE`](#time_zone)
### `ALLOWED_HOSTS`
2017-11-30 00:28:43 +00:00
*Default: * (any)*
This option may be set to a single host or comma-separated list of hosts
2017-11-30 00:28:43 +00:00
(without spaces). This should *always* be set to a specific host or hosts in
production deployments.
2020-01-19 16:49:45 +00:00
See also: [Django's documentation on the ALLOWED_HOSTS setting](https://docs.djangoproject.com/en/3.0/ref/settings/#allowed-hosts)
### `ALLOW_UPLOADS`
2017-11-30 00:28:43 +00:00
*Default: True*
Whether or not to allow uploads (e.g. of Child photos). For some deployments
2020-01-19 16:49:45 +00:00
(AWS, Heroku) this setting will default to False due to the lack of available
persistent storage.
### `AWS_ACCESS_KEY_ID`
*Default: None*
Required to access your AWS S3 bucket, should be uniquely generated per bucket
for security.
See also: [`AWS_STORAGE_BUCKET_NAME`](#aws_storage_bucket_name)
### `AWS_SECRET_ACCESS_KEY`
*Default: None*
Required to access your AWS S3 bucket, should be uniquely generated per bucket
for security.
See also: [`AWS_STORAGE_BUCKET_NAME`](#aws_storage_bucket_name)
### `AWS_STORAGE_BUCKET_NAME`
*Default: None*
If you would like to use AWS S3 for storage on ephemeral storage platforms like
Heroku you will need to create a bucket and add it's name. See django-storages'
2020-01-19 16:49:45 +00:00
[Amazon S3 documentation](https://django-storages.readthedocs.io/en/latest/backends/amazon-S3.html).
### `DEBUG`
2017-11-30 00:28:43 +00:00
*Default: False*
When in debug mode, Baby Buddy will print much more detailed error information
for exceptions. This setting should be *False* in production deployments.
2020-01-19 16:49:45 +00:00
See also [Django's documentation on the DEBUG setting](https://docs.djangoproject.com/en/3.0/ref/settings/#debug).
### `NAP_START_MAX`
2017-11-30 00:28:43 +00:00
*Default: 18:00*
2017-11-30 00:28:43 +00:00
The maximum *start* time (in the instance's time zone) before which a sleep
2020-01-19 16:49:45 +00:00
entry is consider a nap. Expects the 24-hour format %H:%M.
### `NAP_START_MIN`
2017-11-30 00:28:43 +00:00
*Default: 06:00*
2017-11-30 00:28:43 +00:00
The minimum *start* time (in the instance's time zone) after which a sleep
2020-01-19 16:49:45 +00:00
entry is considered a nap. Expects the 24-hour format %H:%M.
### `SECRET_KEY`
2017-11-30 00:28:43 +00:00
*Default: None*
A random, unique string must be set as the "secret key" before Baby Buddy can
2017-11-30 00:28:43 +00:00
be deployed and run.
2020-01-19 16:49:45 +00:00
See also [Django's documentation on the SECRET_KEY setting](https://docs.djangoproject.com/en/3.0/ref/settings/#secret-key).
### `TIME_ZONE`
*Default: Etc/UTC*
The default time zone to use for the instance. See [List of tz database time zones](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones)
for all possible values. This value can be overridden per use from the user
settings form.
2019-05-04 13:05:36 +00:00
## Languages
2020-01-19 16:49:45 +00:00
Baby Buddy includes translation support as of v1.2.2. Language can be set on a
per-user basis from the user settings page (`/user/settings/`). See
[CONTRIBUTING.md](CONTRIBUTING.md#translation) for information about how to
create/update translations.
2019-05-04 13:05:36 +00:00
### Available languages
2020-01-19 16:49:45 +00:00
2019-05-04 13:05:36 +00:00
:us: English (U.S.) *(base)*
:fr: French
2019-06-07 14:38:59 +00:00
:de: German
2020-01-17 03:14:22 +00:00
:mexico: :es: Spanish
2019-05-04 13:05:36 +00:00
:sweden: Swedish
2020-01-17 03:42:49 +00:00
:tr: Turkish
## Import/Export
Baby Buddy uses the [django-import-export application](https://django-import-export.readthedocs.io/)
to provide import and export functionality.
### Export
Export actions are accessible from Baby Buddy's "Database Admin" area (the
Django admin interface). For example, to export all diaper change entries from
Baby Buddy as an Excel file:
1. Log in as a user with "staff" access.
1. From the user menu, click "Database Admin" under the "Site" heading.
1. Click "Diaper Changes" in the list of data types.
1. Click the "Export" button above the filters list on the right side of the
screen.
1. Select the "xlxs" format and click "Submit"
Note: any applied filters will also filter the exported entries. Alternatively,
on the Diaper Change list screen (step 3 above), it is possible to select one
or many individual records and select "Export selected Diaper Changes" from the
"Actions" list.
### Import
Import actions are accessible from Baby Buddy's "Database Admin" area (the
Django admin interface). From the list of entry types in the Database Admin,
select the type to import and click the "Import" button on the list page. The
import screen for a particular type will list the fields generally expected to
be present for an import. Multiple file types -- including csv, xlsx, etc. --
are supported for the import.
The import pages do not provide *detailed* information about the required data
and formats. When an import is attempted, all rows will be checked for errors
and any issues will be reported on screen and will need to be resolved before
the import can be performed.
See the [example import files](core/tests/import) used for tests to get an idea
of the expected data format.
2017-12-05 21:46:15 +00:00
## API
2020-01-19 16:49:45 +00:00
Baby Buddy uses the [Django REST Framework](https://www.django-rest-framework.org/)
2017-12-05 21:46:15 +00:00
(DRF) to provide a REST API.
2017-12-06 00:43:57 +00:00
The only requirement for (most) requests is that the `Authorization` header is
set as described in the [Authentication](#authentication) section. The one
2017-12-06 00:43:57 +00:00
exception is the `/api` endpoint, which lists all available endpoints.
Currently, the following endpoints are available for `GET`, `OPTIONS`, and
2017-12-06 00:43:57 +00:00
`POST` requests:
- `/api/children/`
- `/api/changes/` (Diaper Changes)
- `/api/feedings/`
- `/api/notes/`
- `/api/sleep/`
- `/api/temperature/`
2017-12-06 00:43:57 +00:00
- `/api/timers/`
- `/api/tummy-times/`
- `/api/weight/`
2017-12-05 21:46:15 +00:00
### Authentication
2020-01-19 16:49:45 +00:00
By default, the [TokenAuthentication](https://www.django-rest-framework.org/api-guide/authentication/#tokenauthentication)
and [SessionAuthentication](https://www.django-rest-framework.org/api-guide/authentication/#sessionauthentication)
2017-12-05 21:46:15 +00:00
classes are enabled. Session authentication covers local API requests made by
the application itself. Token authentication allows external requests to be
2017-12-05 21:46:15 +00:00
made.
:exclamation: **In a production environment, token authentication should only
2017-12-05 21:46:15 +00:00
be used for API calls to an `https` endpoint.** :exclamation:
Each user is automatically assigned an API key that can be used for token
2017-12-05 21:46:15 +00:00
authentication. This key can be found on the User Settings page for the logged
in the user. To use a key for an API request, set the request `Authorization`
header to `Token <user-key>`. E.g.
Authorization: Token 2h23807gd72h7hop382p98hd823dw3g665g56
2017-12-05 21:46:15 +00:00
If the `Authorization` header is not set or the key is not valid, the API will
return `403 Forbidden` with additional details in the response body.
2017-12-06 00:43:57 +00:00
### `GET` Method
#### Request
The `limit` and `offset` request parameters can be used to limit
and offset the results set respectively. For example, the following request
will return five diaper changes starting from the 10th diaper change entry:
curl -X GET 'https://[...]/api/changes/?limit=5&offset=10' -H 'Authorization: Token [...]'
{
"count": <int>,
"next": "https://[...]/api/changes/?limit=5&offset=15",
"previous": "https://[...]/api/changes/?limit=5&offset=5",
"results": [...]
}
Field-based filters for specific endpoints can be found the in the `filters`
2017-12-06 00:43:57 +00:00
field of the `OPTIONS` response for specific endpoints.
2017-12-05 21:46:15 +00:00
2017-12-06 00:43:57 +00:00
#### Response
2017-12-05 21:46:15 +00:00
Returns JSON data in the response body in the following format:
{
"count":<int>,
"next":<url>,
"previous":<url>,
"results":[{...}]
}
2017-12-05 21:46:15 +00:00
- `count`: Total number of records (*in the database*, not just the response).
- `next`: URL for the next set of results.
- `previous`: URL for the previous set of results.
- `results`: An array of the results of the request.
2017-12-06 00:43:57 +00:00
### `OPTIONS` Method
2017-12-05 21:46:15 +00:00
2017-12-06 00:43:57 +00:00
#### Request
All endpoints will respond to an `OPTIONS` request with detailed information
about the endpoint's purpose, parameters, filters, etc.
#### Response
Returns JSON data in the response body describing the endpoint, available
options for `POST` requests, and available filters for `GET` requests. The
2017-12-06 00:43:57 +00:00
following example describes the `/api/children` endpoint:
2017-12-05 21:46:15 +00:00
{
"name": "Child List",
"renders": [
"application/json",
"text/html"
],
"parses": [
"application/json",
"application/x-www-form-urlencoded",
"multipart/form-data"
],
"actions": {
"POST": {
"id": {
"type": "integer",
"required": false,
"read_only": true,
"label": "ID"
},
[...]
}
2017-12-06 00:43:57 +00:00
},
"filters": [
"first_name",
"last_name",
"slug"
]
2017-12-05 21:46:15 +00:00
}
2017-12-06 00:43:57 +00:00
### `POST` Method
#### Request
To add new entries for a particular endpoint, send a `POST` request with the
entry data in JSON format in the request body. The `Content-Type` header for
2017-12-06 00:43:57 +00:00
`POST` request must be set to `application/json`.
Regular sanity checks will be performed on relevant data. See the `OPTIONS`
response for a particular endpoint for details on required fields and data
2017-12-06 00:43:57 +00:00
formats.
#### Response
2017-12-05 21:46:15 +00:00
Returns JSON data in the response body describing the added/updated instance or
error details if errors exist. Errors are keyed by either the field in error or
2020-01-19 16:49:45 +00:00
the general string `non_field_errors` (usually when validation involves
2017-12-05 21:46:15 +00:00
multiple fields).
## Contributing
Contributions are welcome! See [CONTRIBUTING.md](CONTRIBUTING.md) for detailed
2020-01-19 16:49:45 +00:00
information about how to contribute to Baby Buddy.