/vacation-portal

A simple portal that handles vacation requests. The backend has been written in PHP and exposes a REST API. The frontend in a SPA written with Vue.js.

Primary LanguagePHP

Vacation Portal

A simple portal that handles vacation requests.
The backend has been written in PHP and exposes a REST API.
The frontend that consumes the API, is a single page application (SPA) implemented with the help of Vue.js javascript framework.
Below you will find the necessary documentation with instructions on how to run this project.

Folder structure

.
├── backend/                 # Source files of the backend
│   ├── sql/                 # A database dump
│   ├── .env.sample          # A sample .env file that contains the required environment variables
│   ├── composer.json        # Project's composer file (dependencies, autoload)
│   ├── ...
├── frontend/                # Source files of the frontend
│   ├── ...         
├── documentation/           # Documentation related files
│   ├── eer-diagram/         # An EER diagram of the database schema
│   ├── phpdoc/              # Documentation files that has been generated with phpDocumentor
│   ├── postman-collection/  # A postman collection with all the endpoints of the api and examples
│   ├── screenshots/         # Some screenshots that demonstrating the frontend interface
└── docker-compose.yml       # A docker-compose yaml file to run the project easily

Installation

I provide some instructions on how to run the project down below. You have the option to use the provided docker setup or run in manually.

Docker

Let's start with docker, as it is the easiest option. Just run the command below or follow the detailed instructions. Make sure though that the ports 80 (backend), 8080(frontend), 8081(phpmyadmin that used during development) are not occupied in your system as they get exposed by the docker containers.

git clone https://github.com/takisrs/vacation-portal.git && \
cd vacation-portal && \
mv backend/.env.sample backend/.env && \
docker-compose up

Detailed instructions:

  1. Clone this repo git clone https://github.com/takisrs/vacation-portal.git
  2. Move to the project's folder cd vacation-portal
  3. Rename the provided sample .env file located in the backend folder which keeps the necessary configuration mv backend/.env.sample backend/.env. It is safe to keep the defaults.
  4. Build the images and spin up the containers with docker-compose up
  5. You can access the frontend at http://localhost:8080

Manually

Backend

You could upload the files of the backend (backend/*) in the web server of your choice but make sure to do the steps below:

  1. Of course, you will need a mysql server and you will have to import the dump file backend/sql/dump.sql
  2. Use the provided .env.sample file and make a .env file where you will have to adjust the configuration (about the connection to the mysql and the smtp server).
  3. Install the required dependencies with composer install

Frontend

  1. Install the required dependecies with npm install
  2. Serve the app in dev mode with npm run serve or build it with npm run build and move the frontend/dist in the webserver of your choice

Demo Accounts

The db dump includes the following demo accounts that you may use:
User
demo@vacationapp.gr
user123#

Admin
admin@vacationapp.gr
admin123#

Backend

Some key notes about the backend:

  • Requires PHP 7.4 with the pdo_mysql extension
  • Follows the MVC architecture
  • Exposes a REST API
  • The authentication / authorization is performed with JWT access tokens
  • Each class / method is documented with DocBlocks
  • You may find the defined routes at backend/src/VacationApp.php, so you could follow the flow of the application starting from there.

Rest API

The rest api exposes the endpoints below. Any required payload is given as a json in the body of the request.
Each endpoint, except the login one, requires an authorization bearer token in the headers.
POST /auth/login public Returns a token to the successfully authenticated users
GET /users admin access Returns a list of all users
POST /users admin access Creates a new user
GET /users/:id admin access Return user's details
POST /users/:id admin access Updates a user
GET /applications user access Returns a list of applications of the authorized user
POST /applications user access Creates a new application
POST /applications/:id/approve admin access Approves an application
POST /applications/:id/reject admin access Rejects an application

You may also find a postman collection at /documentation/postman-collection/collection.json in case you want to check the above endpoints.

Source code documentation


Class: \takisrs\VacationApp

App's main class Initialize the Request, Response, Router objects. Contains the defined routes. Provides a catch block for the whole application execution.

Visibility Function
public __construct() : void
public init() : void
App's main method. It all starts here. It wraps the whole execution in a try/catch block to catch any unhandled exeption and return a meaningful json response to the client.
public registerRoutes() : void
Declares the routes that the app uses.

Class: \takisrs\Controllers\ApplicationController

Application Controller Methods related to applications' handling (list, create, approve, reject).

Visibility Function
public approve() : void
Approves an application The method changes the status of an application to "approved", and informs the user with an email.
public create() : void
Creates a new application and returns the result of the operation
public index() : void
Retrieves and returns the list of applications of the authorized user
public reject() : void
Rejects an application The method changes the status of an application to "rejected", and inform the user with an email.

This class extends \takisrs\Core\Controller


Class: \takisrs\Controllers\UserController

User Controller Handles any request about users (list, view, create, update).

Visibility Function
public create() : void
Creates a new user
public index() : void
Retrieves and returns the list of all users
public single() : void
Retrieves and returns the fields of the requested user
public update() : void
Updates an user

This class extends \takisrs\Core\Controller


Class: \takisrs\Controllers\AuthController

Auth Controller Handles the requests regarding authentication, such as login, signup. Currently, only the login method has been implemented.

Visibility Function
public login() : void
Login

This class extends \takisrs\Core\Controller


Class: \takisrs\Core\Router

Router class

Visibility Function
public __construct(\takisrs\Core\Request $request, \takisrs\Core\Response $response) : void
Router constructor
public get(\string $pattern, \string $controller, \string $method, integer/\int $access) : void
Registers a get route
public matchAndExtractParams(\string $uri, \string $pattern) : bool if uri matches the pattern or not
Checks if uri matches the pattern and extracts the params
public post(\string $pattern, \string $controller, \string $method, integer/\int $access) : void
Registers a post route
public run() : void
Matches the request with the corresponding controller/method and processes it

Class: \takisrs\Core\MySQLConnection

A class that handles the mysql connection Follows the singleton pattern.

Visibility Function
public __construct() : void
Constructor
public getConnection() : \PDO
Returns the PDO connection
public static getInstance() : \takisrs\Core\MySQLConnection
Returns the instance of the MySQLConnection

Class: \takisrs\Core\Controller

Base Controller class Each controller should extend this class.

Visibility Function
public __construct(\takisrs\Core\Request $request, \takisrs\Core\Response $response) : void
Base controller constructor

Class: \takisrs\Core\Response

Response class A simple class that sends the api response

Visibility Function
public send(array $data) : void
Sends a response to the client
public status(int $code) : \takisrs\Core\Response
Sets the response status code

Class: \takisrs\Core\Model

Base Controller class Any model extends this class. Provides some methods that simplify SELECT, CREATE and UPDATE sql queries.

Visibility Function
public __construct() : void
public create() : object/null
Performs an insert query
public find(integer/\int $id) : object/null
Accepts an id and retrieves the corresponding record from the database
public findAll(\string $sort=null) : array
Retrieves all the records of the corresponding table from the database
public findBy(array $params, \string $sort=null) : array/null array of objects
Retrieves a list of records of the database and return an object for each record
public findOneBy(array $params) : object/null
Retrieves a record from the database
public update() : bool
Performs an update query
protected buildWhere(array $params) : array sql where clause and bind params
Gets and array of field-value pairs and returns an sql where clause
protected getBindParams() : array
Returns an array with the pdo bindings
protected mapResultToObject(array $record, \object $object=null) : object
Maps the result of a select query to the corresponding model

Class: \takisrs\Core\HttpException

A simple HttpException class Throw this exception when you want to provide a meaningfull API response to the user with the appropiate status code. Any other exception type returns a 500 status code in the response.

Visibility Function
public __construct(\int $code=500, \string $message='', \Throwable $previous=null) : void
HttpException constructor

This class extends \Exception

This class implements \Throwable


Class: \takisrs\Core\Authenticator

A class that handles the tasks related to JWT authorization

Visibility Function
public static decodeToken(\string $jwt) : array The decoded data
Receives a token, decodes it and returns the data
public static getToken(array $payload) : string a JWT token
Encodes the given payload and returns a JWT token

Class: \takisrs\Core\Request

Request class Helps with the request manipullation.

Visibility Function
public authorizationToken() : string/null
Retrieves the authorization token of the request
public body(\string $key=null) : mixed
Retrieves a parameter from the json request body
public get(\string $key=null) : mixed
Retrieves a $_GET parameter
public getMethod() : string the request method
Returns the request method (POST, GET)
public getUri() : string the uri
Returns the request uri
public header(\string $key=null) : mixed header value
Retrieves a header from the request
public param(\string $key=null) : mixed
Retrieves a param from the request according to the provided key
public post(\string $key=null) : mixed
Retrieves a $_POST parameter
public setParam(\string $key, string/int/\string $value) : \takisrs\Core\Request
Sets a route param
public setUser(\takisrs\Models\User $user) : \takisrs\Core\Request
Sets the authentication user
public user() : \takisrs\Models\User
Returns the authorized user of the request
public validate(array $rulesArr) : bool/null
A simple validation method for all request params (get, post, body)

Class: \takisrs\Helpers\EmailTemplate

Handles email templating and sending

Visibility Function
public __construct(\takisrs\Helpers\sting/\string $templatePath) : void
Constructor
public getBody() : string
Returns email's body
public getSubject() : string
Returns email's subject
public replaceVar(string $key, string/int $value) : \takisrs\Helpers\self
Replaces a variable in the html content with the provided value
public replaceVars(array $data) : \takisrs\Helpers\self
Replaces all the variables in the html content of the email template
public send(\string $email) : void
Sends the email

Class: \takisrs\Models\Application

Application Model class

Visibility Function
public approve() : boolean
Approves the application (Updates status to "approved")
public days() : integer
Returns the duration of the vacation in days
public isApproved() : boolean
Returns true if the application has been approved
public isRejected() : boolean
Returns true if the application has been rejected
public reject() : boolean
Rejects the application (Updates status to "rejected")
public user() : \takisrs\Models\User
Returns application's user object

This class extends \takisrs\Core\Model


Class: \takisrs\Models\User

User Model class

Visibility Function
public applications() : \takisrs\Models\Application[]/null
Returns an array of user's applications
public isAdmin() : boolean
Returns true if the user is an admin
public isUser() : boolean
Returns true if the user is a simple user

This class extends \takisrs\Core\Model

Frontend

Some key notes about the frontend:

  • Requires nodejs 14 if you intend to set it up locally in a dev environment
  • It is a SPA that has been built with the VueJS framework
  • Communicates with the backend through the REST api
  • Keeps a state about the logged in users and sends a bearer authorization token in the headers on each request