GithubHelp home page GithubHelp logo

martijnboland / appoints-api-node Goto Github PK

View Code? Open in Web Editor NEW
72.0 7.0 21.0 92 KB

Appointment Scheduler Rest API build with Node.js.

Home Page: https://appoints-api.azurewebsites.net

JavaScript 99.81% Batchfile 0.19%

appoints-api-node's Introduction

Appoints-Api

Appoints-Api is a simple example appointment scheduler REST API built with Node.js, Express 4 and Mongodb. A client that consumes this API can be found at https://github.com/martijnboland/appoints-client.

Features

  • Create, view, update and delete appointments
  • Token-based authentication with 3rd party providers (Facebook & Google)
  • Hypermedia API (HAL, see http://stateless.co/hal_specification.html)
  • Full integration test suite

Getting started

  1. Node.js needs to be installed on your machine

  2. Make sure you have access to a MongoDB instance, either on your local machine or somewhere in the cloud. The test suite is configured by default to use a local database with the name 'appointstest'

  3. Clone the repository:

     git clone https://github.com/martijnboland/appoints-api-node.git
    
  4. Install packages:

     npm install
    
  5. Create a config file for the development environment by copying /config/example.js to /config/development.js.

  6. Run the server (default on http://localhost:3000/):

     node index.js
    

You can run the integration test suite with:

	npm test (*nix, Mac OS X)
	runtests.bat (Windows)

Usage

When the server is running locally, you can try the api with a browser, curl or an API testing tool like Postman. If you don't have a local server running, you can try the API at https://appoints-api.azurewebsites.net/ instead of http://localhost:3000/.

The default response content type is application/hal+json. It's also possible to request application/json by adding the Accept: application/json header to the request. POST, PUT and PATCH requests need to have their content-type set to application/json.

Start with GET http://localhost:3000/:

{
	"message": "Appoints service API",
	"details": "This is a REST api where you can schedule appointments for <insert business here>",
	"_links": {
		"self": {"href":"/"},
		"me": {"href":"/me"},
		"appointments" : {"href":"/appointments"}
	}
}

Following the links, you can see 2 other resources: /me and /appointments. Let's go to /me and see what happens:

{
	"message": "Access to /me is not allowed.",
	"details": "No Authorization header was found. Format is Authorization: Bearer [token]",
	"_links": {
		"auth_facebook": {"href":"/auth/facebook"},
		"auth_google": {"href":"/auth/google"}
	}
}

Alright, so we're not supposed to view the resource unauthenticated and we need to supply an authorization token. How can we get a token? Perhaps follow one of the links? We're going to try the Google route: http://localhost:3000/auth/google. At this point there are two options:

  1. Do a GET request to http://localhost:3000/auth/google that will redirect to the Google authentication/authorization page that redirects back to our API after successful authorization. After this, we generate our own JWT token and redirect again with the access_token in the hash: http://localhost/auth/loggedin#access_token=eyJ0eXAiOiJK.... From here, things are unfortunately a bit hacky because this is the only place where the API doesn't return a nice JSON response but HTML with a script that posts the access_token back to the opener window:

    if (window.opener) { window.opener.postMessage(window.location.hash.replace("#access_token=", ""), "*"); }
    

This to facilitate browser clients from other domains that use a popup browser window for the authentication flow but can not access the access_token hash due to cross-domain restrictions. With postMessage() it's possible to send values between browser windows and different domains.

  1. Do a POST request to http://localhost:3000/auth/google with an already obtained token via some client API. This generates our authorization token:

    {
    	"message": "Authentication successful",
    	"token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6IjUzN2Y2Yjk4MzFhNTEyYWJjY2Q1OGE5OCIsImVtYWlsIjoibWFydGlqbmJvbGFuZEBnbWFpbC5jb20iLCJkaXNwbGF5TmFtZSI6Ik1hcnRpam4gQm9sYW5kIiwicm9sZXMiOlsiY3VzdG9tZXIiXSwiaWF0IjoxNDAxMTI3NTYxLCJleHAiOjE0MDExMzExNjF9.eFjb_mQ413Dz8YUorVREuCYDvHrrZRopg89m-kD4Jh8",
    	"_links":{
    		"self": {"href":"/"},
    		"me": {"href":"/me"},
    		"appointments": {"href":"/appointments"}
    	}
    }

If things went alright, we now have the authorization token. Try the /me link again but now with the authorization header HTTP HEADER set:

Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6IjUzN2Y2Yjk4MzFhNTEyYWJjY2Q1OGE5OCIsImVtYWlsIjoibWFydGlqbmJvbGFuZEBnbWFpbC5jb20iLCJkaXNwbGF5TmFtZSI6Ik1hcnRpam4gQm9sYW5kIiwicm9sZXMiOlsiY3VzdG9tZXIiXSwiaWF0IjoxNDAxMTI3NTYxLCJleHAiOjE0MDExMzExNjF9.eFjb_mQ413Dz8YUorVREuCYDvHrrZRopg89m-kD4Jh8

which returns:

{
	"_links": {
		"self": {"href":"/users/537f6b9831a512abccd58a98"}
	},
	"userId": "89928749324",
	"provider": "google",
	"email": "[email protected]",
	"displayName": "A google user",
	"roles":["customer"]
}

Looking good! Where can we go next? We still have one link left to try: /appointments. Here we can manage our appointments (create, view, update and delete with the standard GET, POST, PUT, PATCH and DELETE HTTP verbs). Let's create a new appointment by POSTing to /appointments (with the authorization header set properly). The data for the appointment is:

{
  "title": "Fresh haircut",
  "dateAndTime": "2014-06-01T14:45:00.000Z",
  "endDateAndTime": "2014-06-01T15:15:00.000Z",
  "duration": 30,
  "remarks": "Same as last time"
}

The response has HTTP status code 201 (created) and the body contains the newly created appointment:

{
	"_links":{
		"self": {"href":"/appointments/53838715fd51be21ee42b7d4"},
		"user": {
			"href":"/users/537f6b9831a512abccd58a98",
			"title":"A google user"
		}
	},
	"id":"53838715fd51be21ee42b7d4",
	"title":"Fresh haircut",
	"dateAndTime":"2014-06-01T14:45:00.000Z",
	"endDateAndTime": "2014-06-01T15:15:00.000Z",
	"duration":30,
	"remarks":"Same as last time"
}

The appointment is stored in the database and a GET request for /appointments returns all our appointments:

{
	"_links": {
		"self": {"href":"/appointments"}
	},
	"_embedded": {
		"appointment":[{
			"_links": {
				"self": {"href":"/appointments/53838715fd51be21ee42b7d4"},
				"user": {
					"href":"/users/537f6b9831a512abccd58a98",
					"title":"A google user"
				}
			},
			"id":"53838715fd51be21ee42b7d4",
			"title":"Fresh haircut",
			"dateAndTime":"2014-06-01T14:45:00.000Z",
			"endDateAndTime": "2014-06-01T15:15:00.000Z",
			"duration":30,
			"remarks":"Same as last time"
		}]
	},
	"count":1
}

Existing appointments can be modified or deleted at /appointments/:id with the PUT, PATCH and DELETE verbs. Let's say we want to reschedule the appointment. This can be done by sending a PATCH request to /appointments/53838715fd51be21ee42b7d4 with the new date and time:

{
  "dateAndTime": "2014-06-01T17:15:00.000Z",
  "endDateAndTime": "2014-06-01T17:45:00.000Z",
  "remarks": "Same as last time (rescheduled from 14:45 to 17:15)"
}

This returns the modified resource as response with HTTP status code 200:

{
	"_links":{
		"self":{"href":"/appointments/53838715fd51be21ee42b7d4"},
		"user":{
			"href":"/users/537f6b9831a512abccd58a98",
			"title":"A google user"
		}
	},
	"id":"53838715fd51be21ee42b7d4",
	"title":"Fresh haircut",
	"dateAndTime":"2014-06-01T17:15:00.000Z",
	"endDateAndTime": "2014-06-01T17:45:00.000Z",
	"duration":30,
	"remarks":"Same as last time (rescheduled from 14:45 to 17:15)"
}

Security warning

The authorization header contains sensitive information. Always use SSL when deploying an API like this in a production environment.

appoints-api-node's People

Contributors

martijnboland avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

appoints-api-node's Issues

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.