Merge pull request #8 from Sundowndev/develop
[API] Authentication and Task resourcemaster 1.0.0-rc1
commit
9bba703c7c
10
Dockerfile
10
Dockerfile
|
@ -34,12 +34,14 @@ CMD ["php-fpm"]
|
||||||
# https://getcomposer.org/doc/03-cli.md#composer-allow-superuser
|
# https://getcomposer.org/doc/03-cli.md#composer-allow-superuser
|
||||||
ENV COMPOSER_ALLOW_SUPERUSER 1
|
ENV COMPOSER_ALLOW_SUPERUSER 1
|
||||||
|
|
||||||
# Use prestissimo to speed up builds
|
|
||||||
RUN composer global require "hirak/prestissimo:^0.3" --prefer-dist --no-progress --no-suggest --optimize-autoloader --classmap-authoritative --no-interaction
|
|
||||||
|
|
||||||
###> recipes ###
|
###> recipes ###
|
||||||
###< recipes ###
|
###< recipes ###
|
||||||
|
|
||||||
COPY ./server .
|
COPY ./server .
|
||||||
|
|
||||||
RUN composer install
|
# Use prestissimo to speed up builds
|
||||||
|
RUN composer global require "hirak/prestissimo:^0.3" --prefer-dist --no-progress --no-suggest --optimize-autoloader --classmap-authoritative --no-interaction
|
||||||
|
|
||||||
|
RUN composer install
|
||||||
|
|
||||||
|
RUN echo $(cat .env.dist) > .env
|
46
README.md
46
README.md
|
@ -1,33 +1,31 @@
|
||||||
# interview-v1
|
# interview-v1
|
||||||
|
|
||||||
![](https://api.travis-ci.org/Sundowndev/interview-v1.svg)
|
Build status : ![](https://api.travis-ci.org/Sundowndev/interview-v1.svg)
|
||||||
|
|
||||||
## Description
|
## Description
|
||||||
|
|
||||||
1/ Développer en PHP une mini API REST avec output en json
|
1/ Develop a mini PHP REST API with json output
|
||||||
|
|
||||||
Cette api doit:
|
This api must manage 2 objects :
|
||||||
|
- User (id, name, email)
|
||||||
|
- Task (id, user_id, title, description, creation_date, status)
|
||||||
|
|
||||||
- Gérer 2 types d'objets:
|
Create API endpoints to recover a user or task data. (e.g /user/{id})
|
||||||
User (id, name, email)
|
|
||||||
Task (id, user_id, title, description, creation_date, status)
|
|
||||||
|
|
||||||
- Mettre à disposition des endpoints permettant de récupérer les données d'un user et d'une task. (ex: /user/$id)
|
The API must be able to manage users tasks and create the endpoints to:
|
||||||
|
- Fetch the latest tasks
|
||||||
|
- Create a task
|
||||||
|
- Delete a task
|
||||||
|
|
||||||
- L'api doit être capable de manipuler la liste des taches associées à un utilisateur en offrant la possibilité de:
|
While developing this API, you must keep in mind it can evolve at any moment (new resources, new properties in objects ...).
|
||||||
Récupérer cette liste de taches
|
|
||||||
Créer et ajouter une nouvelle tache
|
|
||||||
Supprimer une tache
|
|
||||||
|
|
||||||
En développant cette API, vous devez garder en tête qu'elle est susceptible d'évoluer (nouveaux retours, nouveaux attributs dans les objets)
|
2/ Create a frontend client to call the API
|
||||||
|
|
||||||
2/ Développer un front en HtML/JS/CSS (pas de design nécessaire)
|
- The client must call the api using ajax
|
||||||
|
- We must be able to create/delete an user
|
||||||
|
- Manage user's tasks (read / add / delete)
|
||||||
|
|
||||||
Ce front doit communiquer avec l'api en ajax.
|
(no framework)
|
||||||
On doit pouvoir ajouter/supprimer un utilisateur
|
|
||||||
Gérer la liste des tâches d'un utilisateur (liste / ajout / suppression)
|
|
||||||
|
|
||||||
(pas de framework)
|
|
||||||
|
|
||||||
## Installation and usage
|
## Installation and usage
|
||||||
|
|
||||||
|
@ -51,11 +49,21 @@ The architecture is made of a simple client -> server communication using Docker
|
||||||
|
|
||||||
## Security
|
## Security
|
||||||
|
|
||||||
|
To handle authentication feature, we use JWT authentication.
|
||||||
|
|
||||||
|
JSON Web Token (JWT) is an open standard ([RFC 7519](https://tools.ietf.org/html/rfc7519)) that defines a compact and self-contained way for securely transmitting information between parties as a JSON object. This information can be verified and trusted because it is digitally signed. JWTs can be signed using a secret (with the HMAC algorithm) or a public/private key pair using RSA or ECDSA. [Source](https://jwt.io/introduction/)
|
||||||
|
|
||||||
|
As soon as the user provide valid credentials, we return a JWT token that will be needed for each request the client will send to the API.
|
||||||
|
|
||||||
|
For each request, the user send the JWT token as parameter.
|
||||||
|
|
||||||
|
![JWT explained](https://cdn-images-1.medium.com/max/1400/1*SSXUQJ1dWjiUrDoKaaiGLA.png)
|
||||||
|
|
||||||
## API endpoints
|
## API endpoints
|
||||||
|
|
||||||
| Method / Route | Resource | Description |
|
| Method / Route | Resource | Description |
|
||||||
| --------------------- | ------------------ | ------------ |
|
| --------------------- | ------------------ | ------------ |
|
||||||
| `POST` /auth | Authentification | Connect and get an api key |
|
| `POST` /auth | Authentication | Connect and get an api key |
|
||||||
| `GET` /tasks | Task | Get latest taks |
|
| `GET` /tasks | Task | Get latest taks |
|
||||||
| `GET` /tasks/{id} | Task | Get a task by given id |
|
| `GET` /tasks/{id} | Task | Get a task by given id |
|
||||||
| `POST` /tasks | Task | Create a task |
|
| `POST` /tasks | Task | Create a task |
|
||||||
|
|
|
@ -7,7 +7,7 @@ services:
|
||||||
- "3311:3306"
|
- "3311:3306"
|
||||||
environment:
|
environment:
|
||||||
MYSQL_ROOT_PASSWORD: root
|
MYSQL_ROOT_PASSWORD: root
|
||||||
MYSQL_DATABASE: mysql
|
MYSQL_DATABASE: app1
|
||||||
MYSQL_USER: mysql
|
MYSQL_USER: mysql
|
||||||
MYSQL_PASSWORD: mysql
|
MYSQL_PASSWORD: mysql
|
||||||
|
|
||||||
|
@ -42,3 +42,10 @@ services:
|
||||||
- ./docker/httpd/httpd.conf:/usr/local/apache2/conf/httpd.conf:ro
|
- ./docker/httpd/httpd.conf:/usr/local/apache2/conf/httpd.conf:ro
|
||||||
ports:
|
ports:
|
||||||
- '443:443'
|
- '443:443'
|
||||||
|
|
||||||
|
# For development purposes
|
||||||
|
adminer:
|
||||||
|
image: adminer
|
||||||
|
restart: always
|
||||||
|
ports:
|
||||||
|
- 8080:8080
|
|
@ -1,8 +1,9 @@
|
||||||
### Environment file ###
|
### Environment file ###
|
||||||
MYSQL_USER=mysql
|
MYSQL_USER=root
|
||||||
MYSQL_PASS=mysql
|
MYSQL_PASS=root
|
||||||
MYSQL_HOST=db
|
MYSQL_HOST=db
|
||||||
MYSQL_PORT=3311
|
MYSQL_PORT=3306
|
||||||
MYSQL_DBNAME=mysql
|
MYSQL_DBNAME=app1
|
||||||
### Allow origin for the API ###
|
### Allow origin for the API ###
|
||||||
ALLOW_ORIGIN=^https?://localhost:?[0-9]*$
|
ALLOW_ORIGIN=^https?://localhost:?[0-9]*$
|
||||||
|
APP_SECRET=04980744f74f4ec36ad5a9d5fec8876f
|
|
@ -1,32 +1,84 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
use App\Service\DotEnvParser;
|
||||||
|
use App\Service\JsonResponse;
|
||||||
|
|
||||||
$router->setNamespace('\App\Controller');
|
$router->setNamespace('\App\Controller');
|
||||||
|
|
||||||
$router->before('GET|POST', '/.*', function() use ($router) {
|
$router->before('GET|POST|PUT|DELETE', '/.*', function () use ($router) {
|
||||||
# This will be always executed
|
# This will be always executed
|
||||||
|
$dotEnvParser = new DotEnvParser();
|
||||||
|
$dotEnvParser->run();
|
||||||
|
|
||||||
|
$jsonResponse = new JsonResponse();
|
||||||
|
|
||||||
|
if ($_SERVER['HTTP_ACCEPT'] !== 'application/json') {
|
||||||
|
$code = 400;
|
||||||
|
$message = 'Accept header is not set to "application/json".';
|
||||||
|
print $jsonResponse->create($code, $message, []);
|
||||||
|
exit();
|
||||||
|
} elseif ($_SERVER['REQUEST_METHOD'] != 'GET' && $_SERVER['CONTENT_TYPE'] !== 'application/json') {
|
||||||
|
$code = 400;
|
||||||
|
$message = 'Content-type header is not set to "application/json".';
|
||||||
|
print $jsonResponse->create($code, $message, []);
|
||||||
|
exit();
|
||||||
|
}/* elseif ($_SERVER['HTTP_ORIGIN'] !== getenv('ALLOW_ORIGIN')) {
|
||||||
|
$code = 403;
|
||||||
|
$message = 'Unallowed origin.';
|
||||||
|
print $jsonResponse->create($code, $message, []);
|
||||||
|
exit();
|
||||||
|
}*/
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* API index
|
||||||
|
*/
|
||||||
$router->get('/', 'DefaultController@index');
|
$router->get('/', 'DefaultController@index');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 404 error response
|
||||||
|
*/
|
||||||
|
$router->set404('DefaultController@error');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Session handling routes
|
||||||
|
*/
|
||||||
|
$router->post('/auth', 'SessionController@auth');
|
||||||
|
$router->post('/signup', 'SessionController@signup');
|
||||||
|
$router->post('/logout', 'SessionController@signout');
|
||||||
|
$router->get('/me', 'SessionController@me');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Task resource
|
||||||
|
*/
|
||||||
$router->mount('/tasks', function () use ($router) {
|
$router->mount('/tasks', function () use ($router) {
|
||||||
// get all tasks
|
// Get all tasks
|
||||||
$router->get('/', 'TaskController@getAll');
|
$router->get('/', 'TaskController@getAll');
|
||||||
|
|
||||||
// get one task
|
// Get one task
|
||||||
$router->get('/(\d+)', 'TaskController@get');
|
$router->get('/(\d+)', 'TaskController@get');
|
||||||
|
|
||||||
// create a task
|
// Create a task
|
||||||
$router->post('/', 'TaskController@post');
|
$router->post('/', 'TaskController@post');
|
||||||
|
|
||||||
// update a task
|
// Update a task
|
||||||
$router->put('/(\d+)', 'TaskController@put');
|
$router->put('/(\d+)', 'TaskController@put');
|
||||||
|
|
||||||
// delete a task
|
// Delete a task
|
||||||
$router->delete('/(\d+)', 'TaskController@delete');
|
$router->delete('/(\d+)', 'TaskController@delete');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User resource
|
||||||
|
*/
|
||||||
$router->mount('/users', function () use ($router) {
|
$router->mount('/users', function () use ($router) {
|
||||||
// endpoints for user
|
// Create user (register)
|
||||||
|
$router->post('/', 'DefaultController@index');
|
||||||
|
|
||||||
|
// Get one user
|
||||||
|
$router->get('/(\d+)', 'DefaultController@index');
|
||||||
|
|
||||||
|
// Get one task's tasks
|
||||||
|
$router->get('/(\d+)/tasks', 'DefaultController@index');
|
||||||
});
|
});
|
||||||
|
|
||||||
$router->set404('DefaultController@error');
|
|
|
@ -5,7 +5,7 @@
|
||||||
"license": "WTFPL",
|
"license": "WTFPL",
|
||||||
"require": {
|
"require": {
|
||||||
"bramus/router": "~1.3",
|
"bramus/router": "~1.3",
|
||||||
"josegonzalez/dotenv": "~3.2.0"
|
"codervio/envmanager": "^1.7"
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"psr-4": {
|
"psr-4": {
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "759257fb9b4837a4e886866e36a4c233",
|
"content-hash": "4ac0df3751e41700bc67b558c17957c9",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "bramus/router",
|
"name": "bramus/router",
|
||||||
|
@ -53,88 +53,29 @@
|
||||||
"time": "2017-12-21T20:37:23+00:00"
|
"time": "2017-12-21T20:37:23+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "josegonzalez/dotenv",
|
"name": "codervio/envmanager",
|
||||||
"version": "dev-master",
|
"version": "1.7",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/josegonzalez/php-dotenv.git",
|
"url": "https://github.com/Codervio/Envmanager.git",
|
||||||
"reference": "bc1677b827829f1e1db4a55b8283b4b836617499"
|
"reference": "6b74977f2a048fd2afac144032ccda2808ed2acb"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/josegonzalez/php-dotenv/zipball/bc1677b827829f1e1db4a55b8283b4b836617499",
|
"url": "https://api.github.com/repos/Codervio/Envmanager/zipball/6b74977f2a048fd2afac144032ccda2808ed2acb",
|
||||||
"reference": "bc1677b827829f1e1db4a55b8283b4b836617499",
|
"reference": "6b74977f2a048fd2afac144032ccda2808ed2acb",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"m1/env": "2.*",
|
"php": "^7.0"
|
||||||
"php": ">=5.5.0"
|
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"php-mock/php-mock-phpunit": "^1.1",
|
"phpunit/phpunit": "6.0.*"
|
||||||
"satooshi/php-coveralls": "1.*",
|
|
||||||
"squizlabs/php_codesniffer": "2.*"
|
|
||||||
},
|
|
||||||
"type": "library",
|
|
||||||
"autoload": {
|
|
||||||
"psr-0": {
|
|
||||||
"josegonzalez\\Dotenv": [
|
|
||||||
"src",
|
|
||||||
"tests"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"notification-url": "https://packagist.org/downloads/",
|
|
||||||
"license": [
|
|
||||||
"MIT"
|
|
||||||
],
|
|
||||||
"authors": [
|
|
||||||
{
|
|
||||||
"name": "Jose Diaz-Gonzalez",
|
|
||||||
"email": "dotenv@josegonzalez.com",
|
|
||||||
"homepage": "http://josediazgonzalez.com",
|
|
||||||
"role": "Maintainer"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"description": "dotenv file parsing for PHP",
|
|
||||||
"homepage": "https://github.com/josegonzalez/php-dotenv",
|
|
||||||
"keywords": [
|
|
||||||
"configuration",
|
|
||||||
"dotenv",
|
|
||||||
"php"
|
|
||||||
],
|
|
||||||
"time": "2017-11-27T14:55:32+00:00"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "m1/env",
|
|
||||||
"version": "2.1.2",
|
|
||||||
"source": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://github.com/m1/Env.git",
|
|
||||||
"reference": "294addeedf15e1149eeb96ec829f2029d2017d39"
|
|
||||||
},
|
|
||||||
"dist": {
|
|
||||||
"type": "zip",
|
|
||||||
"url": "https://api.github.com/repos/m1/Env/zipball/294addeedf15e1149eeb96ec829f2029d2017d39",
|
|
||||||
"reference": "294addeedf15e1149eeb96ec829f2029d2017d39",
|
|
||||||
"shasum": ""
|
|
||||||
},
|
|
||||||
"require": {
|
|
||||||
"php": ">=5.3.0"
|
|
||||||
},
|
|
||||||
"require-dev": {
|
|
||||||
"phpunit/phpunit": "4.*",
|
|
||||||
"scrutinizer/ocular": "~1.1",
|
|
||||||
"squizlabs/php_codesniffer": "^2.3"
|
|
||||||
},
|
|
||||||
"suggest": {
|
|
||||||
"josegonzalez/dotenv": "For loading of .env",
|
|
||||||
"m1/vars": "For loading of configs"
|
|
||||||
},
|
},
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"psr-4": {
|
"psr-4": {
|
||||||
"M1\\Env\\": "src"
|
"Codervio\\Envmanager\\": "src/"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"notification-url": "https://packagist.org/downloads/",
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
@ -143,33 +84,38 @@
|
||||||
],
|
],
|
||||||
"authors": [
|
"authors": [
|
||||||
{
|
{
|
||||||
"name": "Miles Croxford",
|
"name": "Marin Sagovac",
|
||||||
"email": "hello@milescroxford.com",
|
"email": "marin@sagovac.com"
|
||||||
"homepage": "http://milescroxford.com",
|
},
|
||||||
"role": "Developer"
|
{
|
||||||
|
"name": "Codervio Community",
|
||||||
|
"homepage": "http://codervio.com"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "Env is a lightweight library bringing .env file parser compatibility to PHP. In short - it enables you to read .env files with PHP.",
|
"description": "Codervio Environment manager",
|
||||||
"homepage": "https://github.com/m1/Env",
|
"homepage": "http://codervio.com",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
".env",
|
".env",
|
||||||
|
"array-env",
|
||||||
"config",
|
"config",
|
||||||
|
"dev-tools",
|
||||||
|
"dot-env",
|
||||||
"dotenv",
|
"dotenv",
|
||||||
|
"dotenv-editor",
|
||||||
"env",
|
"env",
|
||||||
|
"environment",
|
||||||
|
"framework",
|
||||||
"loader",
|
"loader",
|
||||||
"m1",
|
|
||||||
"parser",
|
"parser",
|
||||||
"support"
|
"php"
|
||||||
],
|
],
|
||||||
"time": "2018-06-19T18:55:08+00:00"
|
"time": "2018-03-07T23:55:50+00:00"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"packages-dev": [],
|
"packages-dev": [],
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
"minimum-stability": "stable",
|
"minimum-stability": "stable",
|
||||||
"stability-flags": {
|
"stability-flags": [],
|
||||||
"josegonzalez/dotenv": 20
|
|
||||||
},
|
|
||||||
"prefer-stable": false,
|
"prefer-stable": false,
|
||||||
"prefer-lowest": false,
|
"prefer-lowest": false,
|
||||||
"platform": [],
|
"platform": [],
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
-- Adminer 4.6.3 MySQL dump
|
||||||
|
|
||||||
|
SET NAMES utf8;
|
||||||
|
SET time_zone = '+00:00';
|
||||||
|
SET foreign_key_checks = 0;
|
||||||
|
SET sql_mode = 'NO_AUTO_VALUE_ON_ZERO';
|
||||||
|
|
||||||
|
DROP DATABASE IF EXISTS `app1`;
|
||||||
|
CREATE DATABASE `app1` /*!40100 DEFAULT CHARACTER SET utf8 */;
|
||||||
|
USE `app1`;
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `Session`;
|
||||||
|
CREATE TABLE `Session` (
|
||||||
|
`user_id` int(11) NOT NULL,
|
||||||
|
`token` varchar(255) NOT NULL,
|
||||||
|
`issued_at` datetime NOT NULL,
|
||||||
|
`expire_at` datetime NOT NULL
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||||
|
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `Task`;
|
||||||
|
CREATE TABLE `Task` (
|
||||||
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||||
|
`user_id` int(11) DEFAULT NULL,
|
||||||
|
`title` varchar(255) DEFAULT NULL,
|
||||||
|
`description` varchar(255) DEFAULT NULL,
|
||||||
|
`creation_date` datetime DEFAULT NULL,
|
||||||
|
`status` int(11) DEFAULT NULL,
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
UNIQUE KEY `Task_id_uindex` (`id`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||||
|
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `User`;
|
||||||
|
CREATE TABLE `User` (
|
||||||
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||||
|
`name` varchar(255) NOT NULL,
|
||||||
|
`email` varchar(255) NOT NULL,
|
||||||
|
`password` varchar(255) NOT NULL,
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||||
|
|
||||||
|
|
||||||
|
-- 2018-07-22 00:34:19
|
|
@ -0,0 +1,123 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Controller;
|
||||||
|
|
||||||
|
use App\Repository\SessionRepository;
|
||||||
|
use App\Repository\UserRepository;
|
||||||
|
use App\Service\Database;
|
||||||
|
use App\Service\JsonResponse;
|
||||||
|
use App\Service\Request;
|
||||||
|
use App\Service\Session;
|
||||||
|
|
||||||
|
class SessionController
|
||||||
|
{
|
||||||
|
private $db;
|
||||||
|
private $jsonResponse;
|
||||||
|
private $sessionRepository;
|
||||||
|
private $request;
|
||||||
|
private $session;
|
||||||
|
private $security;
|
||||||
|
private $userRepository;
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->db = new Database();
|
||||||
|
$this->request = new Request();
|
||||||
|
$this->jsonResponse = new JsonResponse();
|
||||||
|
$this->session = new Session($this->db, $this->jsonResponse);
|
||||||
|
$this->security = $this->session->security;
|
||||||
|
$this->sessionRepository = new SessionRepository($this->db, $this->security);
|
||||||
|
$this->userRepository = new UserRepository($this->db);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sign in route
|
||||||
|
*/
|
||||||
|
public function auth()
|
||||||
|
{
|
||||||
|
$body = $this->request->getContent()->jsonToArray();
|
||||||
|
|
||||||
|
if (empty($body['username']) || empty($body['password'])) {
|
||||||
|
print $this->jsonResponse->create(400, 'Please provide an username and password.');
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
$user = $this->userRepository->findOneByUsername($body['username']);
|
||||||
|
|
||||||
|
if (is_null($user) || !$this->security->passwordVerify($body['password'], $user['password'])) {
|
||||||
|
print $this->jsonResponse->create(403, 'Bad credentials.');
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
$token = $this->security->generateToken($user['id']);
|
||||||
|
|
||||||
|
$expire_at = new \DateTime();
|
||||||
|
$expire_at->modify('+1 Day'); // Expire in 1 day
|
||||||
|
|
||||||
|
$this->sessionRepository->create($user['id'], $token, $expire_at->format('Y-m-d H:i:s'));
|
||||||
|
|
||||||
|
print $this->jsonResponse->create(200, 'Welcome ' . $user['name'], [
|
||||||
|
'token' => $token,
|
||||||
|
'expire_at' => $expire_at,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**db
|
||||||
|
* Register route
|
||||||
|
*/
|
||||||
|
public function signup()
|
||||||
|
{
|
||||||
|
$body = $this->request->getContent()->jsonToArray();
|
||||||
|
|
||||||
|
if (empty($body['username']) || empty($body['email']) || empty($body['password'])) {
|
||||||
|
print $this->jsonResponse->create(400, 'Please provide an username, email and password.');
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
$user = [
|
||||||
|
'username' => $body['username'],
|
||||||
|
'email' => $body['email'],
|
||||||
|
'password' => $this->security->passwordHash($body['password']),
|
||||||
|
];
|
||||||
|
|
||||||
|
if (!is_null($this->userRepository->findOneByEmail($user['email']))) {
|
||||||
|
print $this->jsonResponse->create(403, 'Email already registered!');
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->userRepository->create($user['username'], $user['email'], $user['password']);
|
||||||
|
|
||||||
|
print $this->jsonResponse->create(200, 'Success. Now send your credentials to /auth to sign in.', [
|
||||||
|
'username' => $user['username'],
|
||||||
|
'email' => $user['email'],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Signout
|
||||||
|
*/
|
||||||
|
public function signout()
|
||||||
|
{
|
||||||
|
if (!$this->security->isLogged()) {
|
||||||
|
print $this->security->NotAllowedRequest();
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->sessionRepository->deleteByToken($this->security->getBearerToken());
|
||||||
|
|
||||||
|
print $this->jsonResponse->create(200, 'Good bye.', []);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whois route
|
||||||
|
*/
|
||||||
|
public function me()
|
||||||
|
{
|
||||||
|
if (!$this->security->isLogged()) {
|
||||||
|
print $this->security->NotAllowedRequest();
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
print $this->jsonResponse->create(200, 'hello!', $this->session->getUser());
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,23 +5,36 @@ namespace App\Controller;
|
||||||
use App\Service\JsonResponse;
|
use App\Service\JsonResponse;
|
||||||
use App\Service\Database;
|
use App\Service\Database;
|
||||||
use App\Repository\TaskRepository;
|
use App\Repository\TaskRepository;
|
||||||
|
use App\Service\Request;
|
||||||
|
use App\Service\Session;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class TaskController
|
||||||
|
* @package App\Controller
|
||||||
|
*/
|
||||||
class TaskController
|
class TaskController
|
||||||
{
|
{
|
||||||
private $jsonResponse;
|
|
||||||
private $db;
|
private $db;
|
||||||
|
private $request;
|
||||||
|
private $jsonResponse;
|
||||||
|
private $session;
|
||||||
|
private $security;
|
||||||
|
private $repository;
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
$this->jsonResponse = new JsonResponse();
|
|
||||||
$this->db = new Database();
|
$this->db = new Database();
|
||||||
|
$this->request = new Request();
|
||||||
|
$this->jsonResponse = new JsonResponse();
|
||||||
$this->repository = new TaskRepository($this->db);
|
$this->repository = new TaskRepository($this->db);
|
||||||
|
$this->session = new Session($this->db, $this->jsonResponse);
|
||||||
|
$this->security = $this->session->security;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get all tasks
|
* Get all tasks
|
||||||
*
|
*
|
||||||
* Route: /task
|
* Route: /tasks
|
||||||
* Method: GET
|
* Method: GET
|
||||||
*/
|
*/
|
||||||
public function getAll()
|
public function getAll()
|
||||||
|
@ -34,9 +47,9 @@ class TaskController
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get all tasks
|
* Get task by id
|
||||||
*
|
*
|
||||||
* Route: /task/$id
|
* Route: /tasks/$id
|
||||||
* Method: GET
|
* Method: GET
|
||||||
*/
|
*/
|
||||||
public function get($id)
|
public function get($id)
|
||||||
|
@ -45,22 +58,44 @@ class TaskController
|
||||||
$code = ($data != null) ? 200 : 404;
|
$code = ($data != null) ? 200 : 404;
|
||||||
$message = ($data != null) ? "Task found." : "Task not found.";
|
$message = ($data != null) ? "Task found." : "Task not found.";
|
||||||
|
|
||||||
//var_dump($data);
|
|
||||||
|
|
||||||
print $this->jsonResponse->create($code, $message, $data);
|
print $this->jsonResponse->create($code, $message, $data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a task
|
* Create a task
|
||||||
*
|
*
|
||||||
* Route: /task
|
* Route: /tasks
|
||||||
* Method: POST
|
* Method: POST
|
||||||
*/
|
*/
|
||||||
public function post()
|
public function post()
|
||||||
{
|
{
|
||||||
|
if (!$this->security->isLogged()) {
|
||||||
|
print $this->security->NotAllowedRequest();
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
$body = $this->request->getContent()->jsonToArray();
|
||||||
|
|
||||||
|
if (empty($body['title']) || empty($body['description'])) {
|
||||||
|
$code = 400;
|
||||||
|
$message = 'Bad parameters.';
|
||||||
|
|
||||||
|
print $this->jsonResponse->create($code, $message);
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
$user = $this->session->getUser();
|
||||||
|
|
||||||
|
$task = $this->repository->create([
|
||||||
|
'user_id' => $user['id'],
|
||||||
|
'title' => $body['title'],
|
||||||
|
'description' => $body['description'],
|
||||||
|
'status' => 1
|
||||||
|
]);
|
||||||
|
|
||||||
$code = 200;
|
$code = 200;
|
||||||
$message = "";
|
$message = 'Success!';
|
||||||
$data = [];
|
$data = $task;
|
||||||
|
|
||||||
print $this->jsonResponse->create($code, $message, $data);
|
print $this->jsonResponse->create($code, $message, $data);
|
||||||
}
|
}
|
||||||
|
@ -68,14 +103,35 @@ class TaskController
|
||||||
/**
|
/**
|
||||||
* Update a task
|
* Update a task
|
||||||
*
|
*
|
||||||
* Route: /task/$id
|
* Route: /tasks/$id
|
||||||
* Method: PUT
|
* Method: PUT
|
||||||
*/
|
*/
|
||||||
public function put($id)
|
public function put($id)
|
||||||
{
|
{
|
||||||
|
if (!$this->security->isLogged()) {
|
||||||
|
print $this->security->NotAllowedRequest();
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
$task = $this->repository->findOneById($id);
|
||||||
|
$user = $this->session->getUser();
|
||||||
|
|
||||||
|
if ($task['user_id'] !== $user['id']) {
|
||||||
|
print $this->security->NotAllowedRequest();
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
$body = $this->request->getContent()->jsonToArray();
|
||||||
|
|
||||||
|
$task = $this->repository->updateById($id, [
|
||||||
|
'title' => $body['title'] ?? $task['title'],
|
||||||
|
'description' => $body['description'] ?? $task['description'],
|
||||||
|
'status' => $body['status'] ?? $task['status']
|
||||||
|
]);
|
||||||
|
|
||||||
$code = 200;
|
$code = 200;
|
||||||
$message = "";
|
$message = "Task edited.";
|
||||||
$data = [];
|
$data = $task;
|
||||||
|
|
||||||
print $this->jsonResponse->create($code, $message, $data);
|
print $this->jsonResponse->create($code, $message, $data);
|
||||||
}
|
}
|
||||||
|
@ -83,13 +139,28 @@ class TaskController
|
||||||
/**
|
/**
|
||||||
* Delete a task
|
* Delete a task
|
||||||
*
|
*
|
||||||
* Route: /task/$id
|
* Route: /tasks/$id
|
||||||
* Method: DELETE
|
* Method: DELETE
|
||||||
*/
|
*/
|
||||||
public function delete($id)
|
public function delete($id)
|
||||||
{
|
{
|
||||||
|
if (!$this->security->isLogged()) {
|
||||||
|
print $this->security->NotAllowedRequest();
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
$task = $this->repository->findOneById($id);
|
||||||
|
$user = $this->session->getUser();
|
||||||
|
|
||||||
|
if ($task['user_id'] !== $user['id']) {
|
||||||
|
print $this->security->NotAllowedRequest();
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->repository->deleteById($id);
|
||||||
|
|
||||||
$code = 200;
|
$code = 200;
|
||||||
$message = "";
|
$message = "Task deleted.";
|
||||||
$data = [];
|
$data = [];
|
||||||
|
|
||||||
print $this->jsonResponse->create($code, $message, $data);
|
print $this->jsonResponse->create($code, $message, $data);
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Controller;
|
||||||
|
|
||||||
|
class UserController
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
|
@ -0,0 +1,142 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Repository;
|
||||||
|
|
||||||
|
use App\Service\Database;
|
||||||
|
use App\Service\Security;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class SessionRepository
|
||||||
|
* @package App\Repository
|
||||||
|
*/
|
||||||
|
class SessionRepository
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var Database
|
||||||
|
*/
|
||||||
|
private $db;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var Security
|
||||||
|
*/
|
||||||
|
private $security;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var
|
||||||
|
*/
|
||||||
|
private $tableName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TaskRepository constructor.
|
||||||
|
* @param $db
|
||||||
|
*/
|
||||||
|
public function __construct($db, Security $security)
|
||||||
|
{
|
||||||
|
$this->db = $db;
|
||||||
|
$this->security = $security;
|
||||||
|
$this->tableName = 'Session';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function findAll()
|
||||||
|
{
|
||||||
|
$stmt = $this->db->getConnection()->prepare('SELECT * FROM ' . $this->tableName . ' ORDER BY id DESC');
|
||||||
|
$stmt->execute();
|
||||||
|
|
||||||
|
return $stmt->fetchAll(\PDO::FETCH_ASSOC);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $id
|
||||||
|
* @return null
|
||||||
|
*/
|
||||||
|
public function findOneById($id)
|
||||||
|
{
|
||||||
|
$stmt = $this->db->getConnection()->prepare('SELECT * FROM ' . $this->tableName . ' WHERE id = :id');
|
||||||
|
$stmt->bindParam(':id', $id, \PDO::PARAM_INT);
|
||||||
|
$stmt->execute();
|
||||||
|
|
||||||
|
$task = $stmt->fetch(\PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
|
if (!$task) {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
return $task;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function findUserBySessionToken($token)
|
||||||
|
{
|
||||||
|
$stmt = $this->db->getConnection()->prepare('SELECT s.token, s.expire_at, u.id, u.name, u.email FROM ' . $this->tableName . ' AS s INNER JOIN User as u ON s.user_id = u.id WHERE s.token = :token');
|
||||||
|
$stmt->bindParam(':token', $token, \PDO::PARAM_STR);
|
||||||
|
$stmt->execute();
|
||||||
|
|
||||||
|
return $stmt->fetch(\PDO::FETCH_ASSOC);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $user_id
|
||||||
|
* @param $csrf
|
||||||
|
* @param $cookie
|
||||||
|
*/
|
||||||
|
public function create($user_id, $token, $expiration)
|
||||||
|
{
|
||||||
|
$stmt = $this->db->getConnection()->prepare('INSERT INTO Session (`user_id`, `token`, `issued_at`, `expire_at`) VALUES(:user_id, :token, NOW(), :expire_at)');
|
||||||
|
$stmt->bindParam(':user_id', $user_id);
|
||||||
|
$stmt->bindParam(':token', $token);
|
||||||
|
$stmt->bindParam(':expire_at', $expiration);
|
||||||
|
$stmt->execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $id
|
||||||
|
* @param $data
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function updateById($id, $data)
|
||||||
|
{
|
||||||
|
$session = $this->findOneById($id);
|
||||||
|
|
||||||
|
/*$stmt = $this->db->getConnection()->prepare('UPDATE ' . $this->tableName . ' SET user_id = :user_id, title = :title, description = :description, creation_date = :creation_date, status = :status');
|
||||||
|
$stmt->bindParam(':user_id', $data['user_id'] ?? $task['user_id'], \PDO::PARAM_INT);
|
||||||
|
$stmt->bindParam(':title', $data['title'] ?? $task['title'], \PDO::PARAM_STR);
|
||||||
|
$stmt->bindParam(':description', $data['description'] ?? $task['description'], \PDO::PARAM_STR);
|
||||||
|
$stmt->bindParam(':creation_date', $data['creation_date'] ?? $task['creation_date']);
|
||||||
|
$stmt->bindParam(':status', $data['status'] ?? $task['status'], \PDO::PARAM_INT);
|
||||||
|
$stmt->execute();
|
||||||
|
|
||||||
|
return $data;*/
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $id
|
||||||
|
*/
|
||||||
|
public function deleteById($id)
|
||||||
|
{
|
||||||
|
$stmt = $this->db->getConnection()->prepare('DELETE FROM ' . $this->tableName . ' WHERE id = :id');
|
||||||
|
$stmt->bindParam(':id', $id, \PDO::PARAM_INT);
|
||||||
|
$stmt->execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $token
|
||||||
|
*/
|
||||||
|
public function deleteByToken($token)
|
||||||
|
{
|
||||||
|
$stmt = $this->db->getConnection()->prepare('DELETE FROM ' . $this->tableName . ' WHERE token = :token');
|
||||||
|
$stmt->bindParam(':token', $token, \PDO::PARAM_STR);
|
||||||
|
$stmt->execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $userId
|
||||||
|
*/
|
||||||
|
public function deleteByUserId($userId)
|
||||||
|
{
|
||||||
|
$stmt = $this->db->getConnection()->prepare('DELETE FROM ' . $this->tableName . ' WHERE user_id = :user_id');
|
||||||
|
$stmt->bindParam(':user_id', $userId, \PDO::PARAM_INT);
|
||||||
|
$stmt->execute();
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,19 +2,35 @@
|
||||||
|
|
||||||
namespace App\Repository;
|
namespace App\Repository;
|
||||||
|
|
||||||
use App\Service\Database;
|
/**
|
||||||
|
* Class TaskRepository
|
||||||
|
* @package App\Repository
|
||||||
|
*/
|
||||||
class TaskRepository
|
class TaskRepository
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @var Database
|
||||||
|
*/
|
||||||
private $db;
|
private $db;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var
|
||||||
|
*/
|
||||||
private $tableName;
|
private $tableName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TaskRepository constructor.
|
||||||
|
* @param $db
|
||||||
|
*/
|
||||||
public function __construct($db)
|
public function __construct($db)
|
||||||
{
|
{
|
||||||
$this->db = $db;
|
$this->db = $db;
|
||||||
$this->tableName = 'Task';
|
$this->tableName = 'Task';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
public function findAll()
|
public function findAll()
|
||||||
{
|
{
|
||||||
$stmt = $this->db->getConnection()->prepare('SELECT * FROM ' . $this->tableName . ' ORDER BY id DESC');
|
$stmt = $this->db->getConnection()->prepare('SELECT * FROM ' . $this->tableName . ' ORDER BY id DESC');
|
||||||
|
@ -23,6 +39,10 @@ class TaskRepository
|
||||||
return $stmt->fetchAll(\PDO::FETCH_ASSOC);
|
return $stmt->fetchAll(\PDO::FETCH_ASSOC);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $id
|
||||||
|
* @return null
|
||||||
|
*/
|
||||||
public function findOneById($id)
|
public function findOneById($id)
|
||||||
{
|
{
|
||||||
$stmt = $this->db->getConnection()->prepare('SELECT * FROM ' . $this->tableName . ' WHERE id = :id');
|
$stmt = $this->db->getConnection()->prepare('SELECT * FROM ' . $this->tableName . ' WHERE id = :id');
|
||||||
|
@ -38,18 +58,46 @@ class TaskRepository
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $data
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
public function create($data)
|
public function create($data)
|
||||||
{
|
{
|
||||||
//
|
$stmt = $this->db->getConnection()->prepare('INSERT INTO ' . $this->tableName . ' (user_id, title, description, creation_date, status) VALUES(:user_id, :title, :description, NOW(), :status)');
|
||||||
|
$stmt->bindParam(':user_id', $data['user_id'], \PDO::PARAM_INT);
|
||||||
|
$stmt->bindParam(':title', $data['title'], \PDO::PARAM_STR);
|
||||||
|
$stmt->bindParam(':description', $data['description'], \PDO::PARAM_STR);
|
||||||
|
$stmt->bindParam(':status', $data['status'], \PDO::PARAM_INT);
|
||||||
|
$stmt->execute();
|
||||||
|
|
||||||
|
return $data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $id
|
||||||
|
* @param $data
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
public function updateById($id, $data)
|
public function updateById($id, $data)
|
||||||
{
|
{
|
||||||
//
|
$stmt = $this->db->getConnection()->prepare('UPDATE ' . $this->tableName . ' SET title = :title, description = :description, status = :status WHERE id = :id');
|
||||||
|
$stmt->bindParam(':id', $id, \PDO::PARAM_INT);
|
||||||
|
$stmt->bindParam(':title', $data['title'], \PDO::PARAM_STR);
|
||||||
|
$stmt->bindParam(':description', $data['description'], \PDO::PARAM_STR);
|
||||||
|
$stmt->bindParam(':status', $data['status'], \PDO::PARAM_INT);
|
||||||
|
$stmt->execute();
|
||||||
|
|
||||||
|
return $data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $id
|
||||||
|
*/
|
||||||
public function deleteById($id)
|
public function deleteById($id)
|
||||||
{
|
{
|
||||||
//
|
$stmt = $this->db->getConnection()->prepare('DELETE FROM ' . $this->tableName . ' WHERE id = :id');
|
||||||
|
$stmt->bindParam(':id', $id, \PDO::PARAM_INT);
|
||||||
|
$stmt->execute();
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,111 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Repository;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class TaskRepository
|
||||||
|
* @package App\Repository
|
||||||
|
*/
|
||||||
|
class UserRepository
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var Database
|
||||||
|
*/
|
||||||
|
private $db;
|
||||||
|
/**
|
||||||
|
* @var
|
||||||
|
*/
|
||||||
|
private $tableName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TaskRepository constructor.
|
||||||
|
* @param $db
|
||||||
|
*/
|
||||||
|
public function __construct($db)
|
||||||
|
{
|
||||||
|
$this->db = $db;
|
||||||
|
$this->tableName = 'User';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function findAll()
|
||||||
|
{
|
||||||
|
$stmt = $this->db->getConnection()->prepare('SELECT * FROM ' . $this->tableName . ' ORDER BY id DESC');
|
||||||
|
$stmt->execute();
|
||||||
|
|
||||||
|
return $stmt->fetchAll(\PDO::FETCH_ASSOC);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $id
|
||||||
|
* @return null
|
||||||
|
*/
|
||||||
|
public function findOneById($id)
|
||||||
|
{
|
||||||
|
$stmt = $this->db->getConnection()->prepare('SELECT * FROM ' . $this->tableName . ' WHERE id = :id');
|
||||||
|
$stmt->bindParam(':id', $id, \PDO::PARAM_INT);
|
||||||
|
$stmt->execute();
|
||||||
|
|
||||||
|
$user = $stmt->fetch(\PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
|
if (!$user) {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
return $user;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $username
|
||||||
|
* @return null
|
||||||
|
*/
|
||||||
|
public function findOneByUsername($username)
|
||||||
|
{
|
||||||
|
$stmt = $this->db->getConnection()->prepare('SELECT * FROM ' . $this->tableName . ' WHERE name = :username');
|
||||||
|
$stmt->bindParam(':username', $username, \PDO::PARAM_INT);
|
||||||
|
$stmt->execute();
|
||||||
|
|
||||||
|
$user = $stmt->fetch(\PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
|
if (!$user) {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
return $user;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $email
|
||||||
|
* @return null
|
||||||
|
*/
|
||||||
|
public function findOneByEmail($email)
|
||||||
|
{
|
||||||
|
$stmt = $this->db->getConnection()->prepare('SELECT * FROM ' . $this->tableName . ' WHERE email = :email');
|
||||||
|
$stmt->bindParam(':email', $email, \PDO::PARAM_INT);
|
||||||
|
$stmt->execute();
|
||||||
|
|
||||||
|
$user = $stmt->fetch(\PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
|
if (!$user) {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
return $user;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $username
|
||||||
|
* @param $email
|
||||||
|
* @param $password
|
||||||
|
*/
|
||||||
|
public function create($username, $email, $password)
|
||||||
|
{
|
||||||
|
$stmt = $this->db->getConnection()->prepare('INSERT INTO ' . $this->tableName . ' (`name`, `email`, `password`) VALUES(:name, :email, :password)');
|
||||||
|
$stmt->bindParam(':name', $username);
|
||||||
|
$stmt->bindParam(':email', $email);
|
||||||
|
$stmt->bindParam(':password', $password);
|
||||||
|
$stmt->execute();
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,41 +2,51 @@
|
||||||
|
|
||||||
namespace App\Service;
|
namespace App\Service;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class Database
|
||||||
|
* @package App\Service
|
||||||
|
*/
|
||||||
class Database
|
class Database
|
||||||
{
|
{
|
||||||
private $dotEnvParser;
|
|
||||||
private $conn;
|
private $conn;
|
||||||
|
private $dsn;
|
||||||
|
private $options;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Database constructor.
|
||||||
|
*/
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
$this->dotEnvParser = new DotEnvParser();
|
$this->conn = null;
|
||||||
$this->dotEnvParser
|
|
||||||
->parse()
|
|
||||||
->toEnv()
|
|
||||||
->toArray();
|
|
||||||
|
|
||||||
$dsn = "mysql:host=" . $_ENV['MYSQL_HOST'] . ";dbname=" . $_ENV['MYSQL_DBNAME'];
|
$this->dsn = "mysql:host=" . getenv('MYSQL_HOST') . ":".getenv('MYSQL_PORT').";dbname=" . getenv('MYSQL_DBNAME');
|
||||||
$options = array(
|
$this->options = array(
|
||||||
\PDO::ATTR_PERSISTENT => true,
|
\PDO::ATTR_PERSISTENT => true,
|
||||||
\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION
|
\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION
|
||||||
);
|
);
|
||||||
|
|
||||||
try {
|
|
||||||
$this->conn = new \PDO($dsn, $_ENV['MYSQL_USER'], $_ENV['MYSQL_PASS'], $options);
|
|
||||||
} //catch any errors
|
|
||||||
catch (\PDOException $e) {
|
|
||||||
$this->error = $e->getMessage();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the PDO connection instance
|
||||||
|
* @return \PDO
|
||||||
|
*/
|
||||||
public function getConnection()
|
public function getConnection()
|
||||||
{
|
{
|
||||||
|
if (is_null($this->conn)) {
|
||||||
|
try {
|
||||||
|
$this->conn = new \PDO($this->dsn, getenv('MYSQL_USER'), getenv('MYSQL_PASS'), $this->options);
|
||||||
|
} //catch any errors
|
||||||
|
catch (\PDOException $e) {
|
||||||
|
exit($e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return $this->conn;
|
return $this->conn;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* gestion des erreurs de retour d'execution de PDO
|
* Handle PDO execution errors
|
||||||
* @param PDOStatement $stmt
|
* @param \PDOStatement $stmt
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function errorHandler(\PDOStatement $stmt) : void
|
public function errorHandler(\PDOStatement $stmt) : void
|
||||||
|
|
|
@ -2,42 +2,27 @@
|
||||||
|
|
||||||
namespace App\Service;
|
namespace App\Service;
|
||||||
|
|
||||||
use josegonzalez\Dotenv\Loader;
|
use Codervio\Envmanager\Envparser;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class DotEnvParser
|
||||||
|
* @package App\Service
|
||||||
|
*/
|
||||||
class DotEnvParser
|
class DotEnvParser
|
||||||
{
|
{
|
||||||
private $file;
|
private $file;
|
||||||
private $loader;
|
private $parser;
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
$this->file = __DIR__ . '/../../.env';
|
$this->file = __DIR__ . '/../../.env';
|
||||||
$this->loader = new Loader($this->file);
|
|
||||||
|
$this->parser = new Envparser($this->file);
|
||||||
|
$this->parser->load();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public function run()
|
||||||
* Parse the .env file
|
|
||||||
* @return bool|Loader
|
|
||||||
*/
|
|
||||||
public function parse()
|
|
||||||
{
|
{
|
||||||
return $this->loader->parse();
|
$this->parser->run();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
/**
|
|
||||||
* Send the parsed .env file to the $_ENV variable
|
|
||||||
* @return bool|Loader
|
|
||||||
*/
|
|
||||||
public function toEnv()
|
|
||||||
{
|
|
||||||
return $this->loader->toEnv();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return array|null
|
|
||||||
*/
|
|
||||||
public function toArray()
|
|
||||||
{
|
|
||||||
return $this->loader->toArray();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -2,6 +2,10 @@
|
||||||
|
|
||||||
namespace App\Service;
|
namespace App\Service;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class JsonResponse
|
||||||
|
* @package App\Service
|
||||||
|
*/
|
||||||
class JsonResponse
|
class JsonResponse
|
||||||
{
|
{
|
||||||
public function create(int $code, string $message = null, array $data = [])
|
public function create(int $code, string $message = null, array $data = [])
|
||||||
|
@ -12,6 +16,8 @@ class JsonResponse
|
||||||
'data' => $data
|
'data' => $data
|
||||||
];
|
];
|
||||||
|
|
||||||
|
header('Access-Control-Allow-Origin: ' . getenv('ALLOW_ORIGIN'));
|
||||||
|
header('Accept: application/json');
|
||||||
header('Content-Type: application/json');
|
header('Content-Type: application/json');
|
||||||
http_response_code($code);
|
http_response_code($code);
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Service;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class JsonResponse
|
||||||
|
* @package App\Service
|
||||||
|
*/
|
||||||
|
class Request
|
||||||
|
{
|
||||||
|
private $content;
|
||||||
|
|
||||||
|
public function getContent()
|
||||||
|
{
|
||||||
|
$this->content = trim(file_get_contents("php://input")) ?? [];
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function asPlainText(){
|
||||||
|
return (string) $this->content;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function jsonToArray(){
|
||||||
|
return json_decode($this->content, true);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,131 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Service;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class Security
|
||||||
|
* @package App\Service
|
||||||
|
*/
|
||||||
|
class Security
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var Session
|
||||||
|
*/
|
||||||
|
private $session;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var JsonResponse
|
||||||
|
*/
|
||||||
|
private $jsonResponse;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var $secret_key
|
||||||
|
*/
|
||||||
|
private $secret_key;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Security constructor.
|
||||||
|
*/
|
||||||
|
public function __construct(Session $session, JsonResponse $jsonResponse)
|
||||||
|
{
|
||||||
|
$this->session = $session;
|
||||||
|
$this->jsonResponse = $jsonResponse;
|
||||||
|
$this->secret_key = getenv('APP_SECRET');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function generateToken($id)
|
||||||
|
{
|
||||||
|
$token = md5($id . uniqid(rand(), TRUE));
|
||||||
|
|
||||||
|
return $token;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $cookie
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function isLogged()
|
||||||
|
{
|
||||||
|
$session = $this->session->getSession($this->getBearerToken());
|
||||||
|
$today = date("Y-m-d H:i:s");
|
||||||
|
|
||||||
|
if (is_null($session) || $session['expire_at'] < $today) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function NotAllowedRequest()
|
||||||
|
{
|
||||||
|
$code = 403;
|
||||||
|
$message = 'You are not allowed to perform this request.';
|
||||||
|
$data = [];
|
||||||
|
|
||||||
|
return $this->jsonResponse->create($code, $message, $data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $password
|
||||||
|
* @return bool|string
|
||||||
|
*/
|
||||||
|
public function passwordHash($password)
|
||||||
|
{
|
||||||
|
return password_hash($password, PASSWORD_BCRYPT, [
|
||||||
|
'cost' => 12
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $password
|
||||||
|
* @param $hash
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function passwordVerify($password, $hash)
|
||||||
|
{
|
||||||
|
return \password_verify($password, $hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get hearder Authorization
|
||||||
|
* */
|
||||||
|
function getAuthorizationHeader()
|
||||||
|
{
|
||||||
|
$headers = null;
|
||||||
|
if (isset($_SERVER['Authorization'])) {
|
||||||
|
$headers = trim($_SERVER["Authorization"]);
|
||||||
|
} else if (isset($_SERVER['HTTP_AUTHORIZATION'])) { //Nginx or fast CGI
|
||||||
|
$headers = trim($_SERVER["HTTP_AUTHORIZATION"]);
|
||||||
|
} elseif (function_exists('apache_request_headers')) {
|
||||||
|
$requestHeaders = apache_request_headers();
|
||||||
|
// Server-side fix for bug in old Android versions (a nice side-effect of this fix means we don't care about capitalization for Authorization)
|
||||||
|
$requestHeaders = array_combine(array_map('ucwords', array_keys($requestHeaders)), array_values($requestHeaders));
|
||||||
|
//print_r($requestHeaders);
|
||||||
|
if (isset($requestHeaders['Authorization'])) {
|
||||||
|
$headers = trim($requestHeaders['Authorization']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $headers;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get access token from header
|
||||||
|
*/
|
||||||
|
function getBearerToken()
|
||||||
|
{
|
||||||
|
$headers = $this->getAuthorizationHeader();
|
||||||
|
// HEADER: Get the access token from the header
|
||||||
|
if (!empty($headers)) {
|
||||||
|
if (preg_match('/Bearer\s(\S+)/', $headers, $matches)) {
|
||||||
|
return $matches[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,53 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Service;
|
||||||
|
|
||||||
|
use App\Repository\SessionRepository;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class Session
|
||||||
|
* @package App\Service
|
||||||
|
*/
|
||||||
|
class Session
|
||||||
|
{
|
||||||
|
private $db;
|
||||||
|
private $sessionRepository;
|
||||||
|
public $security;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Session constructor.
|
||||||
|
*/
|
||||||
|
public function __construct(Database $database, JsonResponse $jsonResponse)
|
||||||
|
{
|
||||||
|
$this->db = $database;
|
||||||
|
$this->security = new Security($this, $jsonResponse);
|
||||||
|
$this->sessionRepository = new SessionRepository($this->db, $this->security);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $cookie
|
||||||
|
* @return mixed|null
|
||||||
|
*/
|
||||||
|
public function getSession($token)
|
||||||
|
{
|
||||||
|
$stmt = $this->db->getConnection()->prepare('SELECT * FROM Session WHERE token = :token');
|
||||||
|
$stmt->bindParam(':token', $token);
|
||||||
|
$stmt->execute();
|
||||||
|
|
||||||
|
$session = $stmt->fetch(\PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
|
if (!$session) {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
return $session;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getUser()
|
||||||
|
{
|
||||||
|
return $this->sessionRepository->findUserBySessionToken($this->security->getBearerToken());
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue