Schedule Booking app is powered by a GraphQL API. GraphQL is a query language that allows clients to talk to an API server. Unlike REST, it gives the client control over how much or how little data they want to request about each object and allows relations within the object graph to be traversed easily.
To learn more about GraphQL language and its concepts, see the official GraphQL website.
The API endpoint is available at /graphql/
and requires queries to be submitted using HTTP POST
method and the application/json
content type.
The API provides simple CURD operation. The application has simple data flow where
authenticated users can create their availabilities slots and other users can
book these slots. Other uses can also see all the bookings of a user.
CURD operations are provided on authenticated availability endpoint using JWT
authentication
mechanism. API provides both types of operations:
- Public (search & book slots in availability.)
- Private (create/update/delete availabilities)
Project Requirements:
- Users can create a schedule of available dates and times and select their desired meeting intervals (15 min / 30 min / 45 min)
- allow the user to do CRUD operations ( create / read / update / delete ) on his available schedule
- Non-users can view all available timings for a specific user
- Non-users can reserve a specific time by providing their full name and email for the meeting
- Non-user can’t reserve a time that has been already reserved
How to run the API
I have used GraphiQL
django app for running the application & testing the quries. GraphiQL is an in-browser tool for writing, validating, and
testing GraphQL queries. Follow the step by step guide below to run & test the GraphQL quries. I have also provided demo quries with their responses below.
This project is created and tested with Python 3.8.10
Create and activate python3.8 virtual env.
-
python3 -m venv ./venv
-
source venv/bin/activate
The next step is to set up the devstack by running the following make
command. If the make
command fails for you
try the alternative.
make setup
OR
pip install -r requirements.txt
python manage.py migrate
python manage.py loaddata ./scheduler/meeting_scheduler/factories/users.json
python manage.py createsuperuser
make run
ORpython manage.py runserver
make test
OR pytest
- User endpoints
api/graphql:login
(mutation) Login & obtain token for the userapi/graphql:verify_token
(mutation): Obtain JSON web token for given user.
- Availability endpoints
api/graphql:create_availability
Create Availability (mutation)api/graphql:availabilities
Read All (your*) availabilities (query)api/graphql:availability
Read (your*) one availability (query)api/graphql:delete_availability
Delete availability (mutation)api/graphql:update_availability
Update (your*) availability (mutation)
- Booking endpoints
api/graphql:bookings_by_user
Read bookings of users given their usernameapi/graphql:create_booking
Create booking for users- Validation for overlapping booking
- Validation for availability exists
- Validation for booking already exists
This endpoint provides basic authentication for the app. Login mutation is required for fetching the auth token and making API calls for private views such as creating availabilities.
mutation {
login(username:"admin", password:"admin"){
success,
errors,
token,
user {
username
}
}
}
{
"data": {
"login": {
"success": true,
"errors": null,
"token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6ImFkbWluIiwiZXhwIjoxNjQwMjkxNzgzLCJvcmlnSWF0IjoxNjQwMjkxNDgzfQ.z5fTy-B8rdUp-g58rPKejw9FYt5pWubPCwQZMR5tiU8",
"user": {
"username": "admin"
}
}
}
}
mutation{
verifyToken(token:"token") {
success
errors
}
}
The JWT
token will be used to create new availability.
The token should be passed in the request header Authorization. e.g. {"Authorization": "JWT {{token}}"}
mutation {
createAvailability(
availabilityFrom:"2022-08-17T09:00:00",
availabilityTo:"2022-08-17T05:00:00",
timeIntervalMints:15
){
success,
availability{
id,
}
}
}
{
"data": {
"createAvailability": {
"success": true,
"availability": {
"id": "2"
}
}
}
}
query{
availabilities {
edges {
node {
id
fromTime,
toTime,
intervalMints
}
}
}
}
{
"data": {
"availabilities": {
"edges": [
{
"node": {
"id": "QXZhaWxhYmlsaXR5VHlwZTox",
"fromTime": "2021-01-14T09:00:00",
"toTime": "2021-01-14T05:00:00",
"intervalMints": "Thirty (30) mints"
}
},
{
"node": {
"id": "QXZhaWxhYmlsaXR5VHlwZToz",
"fromTime": "2022-08-21T09:00:00",
"toTime": "2022-08-21T09:00:00",
"intervalMints": "Thirty (30) mints"
}
},
]
}
}
}
query{
availability(id:"QXZhaWxhYmlsaXR5VHlwZTox"){
id,
fromTime
toTime
intervalMints
}
}
{
"data": {
"availability": {
"id": "QXZhaWxhYmlsaXR5VHlwZTox",
"fromTime": "2022-08-17T09:00:00+00:00",
"toTime": "2022-08-17T05:00:00+00:00",
"intervalMints": "Fifteen (15) mints"
}
}
}
mutation {
deleteAvailability(id:"QXZhaWxhYmlsaXR5VHlwZTox") {
success
error
}
}
{
"data": {
"deleteAvailability": {
"success": true
"error": null
}
}
}
mutation {
updateAvailability(id:"QXZhaWxhYmlsaXR5VHlwZTox", availabilityFrom:"2021-01-14T09:00:00", availabilityTo: "2021-01-14T05:00:00"){
availability{
id
fromTime
toTime
intervalMints
}
success,
error
}
}
{
"data": {
"updateAvailability": {
"availability": {
"id": "1",
"fromTime": "2021-01-14T09:00:00",
"toTime": "2021-01-14T05:00:00",
"intervalMints": "Fifteen (15) mints"
},
"success": true
"error": null
}
}
}
The booking queries can be used without login or providing JWT
auth token. These quries
provide reading and booking user's availabilities.
mutation{
createBooking(
email: "[email protected]"
fullName:"Demo",
username: "admin",
targetDate:"2021-12-23",
targetTime: "11:30"
totalTime: 15,
){
success,
booking {
id
}
}
}
{
"errors": [
{
"message": "admin has no availability in this slot.",
"locations": [
{
"line": 8,
"column": 3
}
],
"path": [
"createBooking"
]
}
],
"data": {
"createBooking": null
}
}
{
"errors": [
{
"message": "The slot is overlapping with other bookings.",
"locations": [
{
"line": 62,
"column": 3
}
],
"path": [
"createBooking"
]
}
],
"data": {
"createBooking": null
}
}
{
"data": {
"createBooking": {
"success": true,
"booking": {
"id": "Qm9va2luZ1R5cGU6NA=="
}
}
}
}
query {
bookings(username:"admin") {
edges {
node {
id
fullName
email
date
startTime
endTime
totalTime
}
}
}
}
"data": {
"bookings": {
"edges": [
{
"node": {
"id": "Qm9va2luZ1R5cGU6MQ==",
"fullName": "Awa",
"email": "[email protected]",
"date": "2021-12-17",
"startTime": "11:30:00",
"endTime": "11:45:00",
"totalTime": 15
}
},
{
"node": {
"id": "Qm9va2luZ1R5cGU6Mg==",
"fullName": "Demo",
"email": "[email protected]",
"date": "2021-12-23",
"startTime": "11:30:00",
"endTime": "11:45:00",
"totalTime": 15
}
},
]
}
}