Public | Automated Build

Last pushed: 2 years ago
Short Description
Basic symfony2 JWT API with user signup and a vue-router frontend
Full Description

API thingie

Thing that does stuff

Requirements

  • On Mac, Windows dev: VMWare Fusion and Homebrew
  • dev: docker-machine + docker-compose
  • the inanimatt/sf2api:develop base image (you can build this yourself: docker build -t inanimatt/sf2api:develop .)

Frontend development

Setup for frontend dev (on Mac. YMMV):

  • brew update && brew install node
  • npm install
# install dependencies
npm install

# serve with hot reload at localhost:8080
npm run dev

# build for production with minification
npm run build

# run unit tests
npm test

For detailed explanation on how things work, consult the docs for vue-loader.

API Development setup

Docker setup

If you haven't done this before for another project:

  • brew update && brew install docker-machine docker-compose
  • docker-machine create dev --driver vmwarefusion
  • docker-machine ip dev will give you the IP address to add to /etc/hosts to point at, e.g. 172.16.141.139 cw.dev
  • eval "$(docker-machine env dev)"

Otherwise it's just:

  • docker-machine start dev
  • eval "$(docker-machine env dev)"
  • Send your API calls to https://cw.dev/api/. A sample Paw file is included, just change the token and you can test the endpoints and generate code for your app.

Starting the dev environment

  • docker-compose up

The first time you do this, it'll download the inanimatt/cwapp:develop docker image, which will take a few minutes, then build the development box on top of it, which pretty much just backs up and resets the database on startup. After that it should be quicker.

If you get an error about not being able to find inanimatt/cwapp:develop, then you don't have access to the docker hub repository. You can build the image locally by running docker built -t inanimatt/cwapp:develop .

You should see something like this at the end of pages of crap:

cwapp_app_1      | 2015-11-25 15:22:49,590 INFO success: fpm entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)
cwapp_app_1      | 2015-11-25 15:22:49,591 INFO success: nginx entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)

Like "grunt serve", this will stay up until you hit Ctrl-C, then it'll shut down. Alternatively you can run docker-compose up -d to make it run in the background, then run docker-compose stop when you're done. If you do that, you won't see any messages on screen if processes in the containers fail.

If you need to access the docker tools or server in new terminal tabs/windows, just run eval "$(docker-machine env dev)". You can test if it worked by running docker ps.

Cleaning up

  • docker-machine stop dev -- shut down the docker VM if you need the CPU & memory back.

Really cleaning up

Docker containers are instances of docker images. Over time these can build up to take up a lot of space. You can run docker-compose rm (ids) to remove your container instances, but the disk images will remain.

You can view all past container instances by running docker ps -a and remove them individually with docker rm <name>. To go all-out and delete all instances, run docker rm $(docker ps -aq).

Docker images can be listed with docker images. Remove images with docker rmi <image id> or all images with docker rmi $(docker images -q) -- but if you do this, the next time you build will take a long time and a lot of downloading!

Database

The dev environment is reset every time the dev container starts. That means it gets a new SSL key and the database is reset. The previous database is saved in db-previous.sql just in case there was something there you wanted. If you want to maintain database content between builds, then update var/initialdb.sql:

docker exec -it cwapp_db_1 mysqldump -u root -phairnet app > db.sql

To edit or query the database manually:

docker exec -it cwapp_db_1 mysql -u root -phairnet app

The initial db contains a test dataset in the test namespace, and a number of test users. You can rebuild these from the initialdb file by just restarting the container, or reset the database while it's running by running docker exec -ti cwapp_cwapp_1 bin/console haute:fix:load.

Configuration

Generally all runtime configuration is held in environment variables. Unlike in regular Symfony projects, environment variables will override configuration variables when set. So docker-compose.yml overrides docker/base/Dockerfile, which overrides app/config/parameters.yml.

Rebuilding the containers

If you have access to the Docker Hub account and bitbucket repo, Docker Hub automatically rebuilds the base container whenever you push to bitbucket. It takes about 10-12 minutes to rebuild the boxes, but you probably don't need to worry about this unless you've changed the docker environment.

If you do need to rebuild your dev box because the base container has changed:

  • docker pull inanimatt/cwapp:develop
  • docker-compose rm -f app && docker-compose build app

API Endpoints

Conventions

All endpoints (other than login and signup) require a valid authorisation token, obtained from /api/account/login. The token is a JWT, so can also be read by your application to retrieve the username.

Almost all endpoints allow you to provide an ?include= URL parameter which will expand embedded objects. Available includes are listed for each endpoint, but these can also be nested up to 3 levels, for example: /{namespace}/topics?include=owner,posts.replies.

Pagination works through the page= and limit= URL parameters. Default limit is 10 and the first page is 1 (not 0). Result sets will contain a meta section with the current page, the total number of results, and links to the next and previous pages, e.g.:

{
  "data": [
  ],
  "meta": {
    "page": 2,
    "count": 100,
    "nextPage": 3,
    "previousPage": 1,
    "next": "https://cw.dev:9443/api/account/subscriptions/?limit=10&page=3",
    "previous": "https://cw.dev:9443/api/account/subscriptions/?limit=10&page=1"
  }
}

All results from the API are returned in this format (except the meta section is missing when there is no metadata). The data section will either be a single object or an array of objects.

The service will return the following HTTP response codes:

  • 200 OK - standard response to GET requests and edits
  • 201 Created - when creating objects
  • 204 No content - usually on DELETE requests
  • 422 Unprocessable entity - validation errors, invalid data
  • 500 - application error

Account endpoints

POST /api/account/login

Fetch a JWT token to use the rest of the API.

Request body
{
  "email": "dot@dotat.at",
  "password": "some super secure password"
}
Response body (success)
{
  "data": {
    "token": "eyJ0eXAiOiJKV1MiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6Imlkb29sZXlAc3RyZWljaC5jb20iLCJpYXQiOjE0NTE4MTc1MTAsImV4cCI6MTQ1MTkwMzkxMH0.xUYpAc5rbKaL9yFttRHANMb5ObwFWE6g75ZFTx7BtJs"
  }
}
Response body (error)
{
  "data": {
    "status": "error",
    "code": "401",
    "message": "Unauthorized"
  }
}

POST /api/account/signup

Create an account

Request body
{
  "email": "dot@dotat.at",
  "password": "some super secure password",
  "displayName": "optional name shown to other users"
}
Response body (success)
{
  "data": {
    "status": "success",
    "token": "eyJ0eXAiOiJKV1MiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6Imlkb29sZXlAc3RyZWljaC5jb20iLCJpYXQiOjE0NTE4MTc1MTAsImV4cCI6MTQ1MTkwMzkxMH0.xUYpAc5rbKaL9yFttRHANMb5ObwFWE6g75ZFTx7BtJs"
  }
}
Response body (error)
{
  "data": {
    "status": "error",
    "message": "ERROR: That email address is already registered.\n"
  }
}

POST /api/account/verify

Please note that you do have to be logged in to verify your email address - i.e., present a valid Authorization: Bearer <jwt> header with this request.

Request body
{
  "token": "IrZXZLBosGy0oW7RjDiHgmEDUrf="
}
Response body (success)
{
  "data": {
    "status": "success",
    "message": "Email address verified"
  }
}
Response body (error)
{
  "data": {
    "status": "error",
    "message": "ERROR: That email address is already registered.\n"
  }
}

POST /api/account/password-reset

Request a password reset. You do not need to be logged in to make this request, obviously

Request body
{
  "email": "you@yourhost.com"
}
Response body (success)
{
  "data": {
    "status": "success",
    "message": "Check your email for a reset token"
  }
}
Response body (error)
{
  "data": {
    "status": "error",
    "message": "No such account"
  }
}

POST /api/account/password-reset/reset

Complete a password reset. You do not need to be logged in to make this request, obviously.

Request body
{
  "email": "you@yourhost.com",
  "password":"new password",
  "token":"rPVYgM4fZfa32sTyVELKUw"
}
Response body (success)
{
  "data": {
    "status": "success",
    "message": "New password accepted",
    "token": "a new JWT"
  }
}
Response body (error)
{
  "data": {
    "status": "error",
    "message": "New password is invalid"
  }
}

GET /api/account/

Fetch the current user account

Available includes
  • subscriptions - subscriptions
  • subscriptions.artist - subscriptions with embedded artist details
Response body
{
  "data": {
    "id": "84a9e96c-b08f-11e5-8eb3-0242ac110002",
    "created": "2015-04-18T20:23:58+00:00",
    "updated": "2015-04-18T20:23:58+00:00",
    "email": "lennie43@example.com",
    "lastLogin": "2016-01-01T14:08:03+00:00",
    "displayName": "PurpleFox"
  }
}

PATCH /api/account/

Modify the current user account

Available includes
  • subscriptions - subscriptions
  • subscriptions.artist - subscriptions with embedded artist details
Request body
{
  "data": {
    "email": "lennie43@example.com",
    "displayName": "PurpleFox"
  }
}
Response body
{
  "data": {
    "id": "84a9e96c-b08f-11e5-8eb3-0242ac110002",
    "created": "2015-04-18T20:23:58+00:00",
    "updated": "2015-04-18T20:23:58+00:00",
    "email": "lennie43@example.com",
    "lastLogin": "2016-01-01T14:08:03+00:00",
    "displayName": "PurpleFox"
  }
}

DELETE /api/account/

Delete the current user account. Returns a 204 No Content response.

Docker Pull Command
Owner
inanimatt
Source Repository

Comments (0)