Compare commits
18 Commits
832bf929dc
...
main
Author | SHA1 | Date | |
---|---|---|---|
3c1769326f | |||
d6fa758482 | |||
27c240a714 | |||
44c7988429 | |||
19b02d7089 | |||
cbd55cec2d | |||
913db80c30 | |||
129c0c1264 | |||
77b9785dc0 | |||
fd91f7985d | |||
e38bef492e | |||
44cb07fe0b | |||
0bcd0f8483 | |||
755784a870 | |||
b844041ea9 | |||
e2d3fc3cee | |||
d08d58410a | |||
b9dc0fc5fe |
76
README.md
76
README.md
@ -1,3 +1,77 @@
|
||||
# test-php-rest-api-user
|
||||
|
||||
Тестовое задание REST API на PHP
|
||||
**Тестовое задание REST API на PHP**
|
||||
|
||||
## Установка / Запуск
|
||||
|
||||
### Первый способ (простой)
|
||||
1. Открыть корневую директорию сайта (в которой файл `installed`)
|
||||
2. Открыть консоль в данной директории
|
||||
3. Выполнить комманду `php -S 0.0.0.0:8888`
|
||||
4. Теперь сайт доступен по адресу [http://localhost:8888](http://localhost:8888)
|
||||
|
||||
### Второй способ (сложнее)
|
||||
1. Установить `nginx` и `php-fpm`
|
||||
2. Поместить содержимое сайта в нужную директорию
|
||||
3. Настроить **nginx** так, как этот делается для **Wordpress**
|
||||
4. Теперь сайт доступен по адресу который указан в nginx (обычно это [http://localhost:80](http://localhost:80))
|
||||
|
||||
|
||||
## Конфигурация
|
||||
Все необходимое для настройки и конфигурации сайта находится в директории `config`
|
||||
|
||||
### `0000.root.php`
|
||||
Содержит базовую информацию о сайте (не важную для API)
|
||||
|
||||
### `0001.db.php`
|
||||
Содержит настройки подключения к Базе Данных
|
||||
|
||||
### `0005.user.php`
|
||||
Содержит конфигурацию для работы с пользователями
|
||||
|
||||
|
||||
## Документация API
|
||||
|
||||
### [Postman](https://www.postman.com/material-observer-62618807/workspace/public-data/collection/37579698-ff75f993-cc82-4704-aea4-612718b8a06b?action=share&creator=37579698)
|
||||
|
||||
### POST `/api/v1/createUser`
|
||||
Создание пользователя
|
||||
|
||||
Параметр | Описание
|
||||
--- | ---
|
||||
login | Обязательное поле (1-32 символа)
|
||||
password | Обязательное поле (от 8 символов)
|
||||
|
||||
|
||||
### POST `/api/v1/authUser`
|
||||
Авторизация и получение токена
|
||||
|
||||
Параметр | Описание
|
||||
--- | ---
|
||||
login | Обязательное поле (1-32 символа)
|
||||
password | Обязательное поле (от 8 символов)
|
||||
|
||||
|
||||
### GET `/api/v1/getUser`
|
||||
Получение информации о пользователе
|
||||
|
||||
Параметр | Описание
|
||||
--- | ---
|
||||
login | Обязательное поле (1-32 символа)
|
||||
|
||||
|
||||
### PATCH `/api/v1/updateUserInfo`
|
||||
Обновление поля info у пользователя
|
||||
|
||||
Параметр | Описание
|
||||
--- | ---
|
||||
token | Обязательное поле (токен, который выдали при авторизации)
|
||||
newInfo | Обязательное поле (без ограничений)
|
||||
|
||||
|
||||
### DELETE `/api/v1/deleteUser`
|
||||
Удаление пользователя
|
||||
|
||||
Параметр | Описание
|
||||
--- | ---
|
||||
token | Обязательное поле (токен, который выдали при авторизации)
|
||||
|
5
config/0005.user.php
Normal file
5
config/0005.user.php
Normal file
@ -0,0 +1,5 @@
|
||||
<?php
|
||||
$config['user'] = [
|
||||
'secret' => 'testing',
|
||||
'tokenLifetime' => 300, // in secs
|
||||
];
|
111
engine/class/0005.user.php
Normal file
111
engine/class/0005.user.php
Normal file
@ -0,0 +1,111 @@
|
||||
<?php
|
||||
class User {
|
||||
private static $secret = '';
|
||||
private static $tokenLifetime = 0;
|
||||
|
||||
|
||||
public static function init($config) {
|
||||
self::$secret = $config['secret'];
|
||||
self::$tokenLifetime = $config['tokenLifetime'];
|
||||
|
||||
if(!Root::installed())
|
||||
self::createTables();
|
||||
}
|
||||
|
||||
public static function createTables() {
|
||||
DB::getQuery('main',
|
||||
'CREATE TABLE IF NOT EXISTS `users` (
|
||||
`id` INT(11) NOT NULL AUTO_INCREMENT,
|
||||
`login` VARCHAR(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
|
||||
`password` VARCHAR(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
|
||||
`info` TEXT CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
|
||||
`reg_dt` INT(11) NOT NULL,
|
||||
`online_dt` INT(11) NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
)
|
||||
ENGINE = InnoDB
|
||||
CHARSET=utf8
|
||||
COLLATE utf8_general_ci'
|
||||
);
|
||||
}
|
||||
|
||||
public static function create($login, $password) {
|
||||
$login = trim($login);
|
||||
$password = trim($password);
|
||||
|
||||
if(self::get($login))
|
||||
return false;
|
||||
|
||||
$password = password_hash($password, PASSWORD_BCRYPT);
|
||||
DB::getQuery('main',
|
||||
'INSERT INTO `users` (`login`, `password`, `info`, `reg_dt`, `online_dt`) VALUES (?, ?, "", ?, ?)',
|
||||
[$login, $password, time(), time()]
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function updateInfo($token, $newInfo) {
|
||||
$newInfo = trim($newInfo);
|
||||
|
||||
if(!$login = self::checkToken($token))
|
||||
return false;
|
||||
|
||||
DB::getQuery('main', 'UPDATE `users` SET `info` = ? WHERE `login` = ?', [$newInfo, $login]);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function delete($token) {
|
||||
if(!$login = self::checkToken($token))
|
||||
return false;
|
||||
|
||||
DB::getQuery('main', 'DELETE FROM `users` WHERE `login` = ?', $login);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function auth($login, $password) {
|
||||
$login = trim($login);
|
||||
$password = trim($password);
|
||||
$user = self::get($login);
|
||||
|
||||
if(!password_verify($password, $user->password))
|
||||
return false;
|
||||
|
||||
$until = time() + self::$tokenLifetime;
|
||||
$hash = hash('sha256', $login.'|'.$user->password.'|'.$until.'|'.self::$secret);
|
||||
|
||||
self::updateOnline($login);
|
||||
|
||||
return rtrim(strtr(base64_encode($login.'|'.$user->password.'|'.$until.'|'.$hash), '+/', '-_'), '=');
|
||||
}
|
||||
|
||||
public static function get($login) {
|
||||
return DB::getQuery('main', 'SELECT * FROM `users` WHERE `login` = ?', $login);
|
||||
}
|
||||
|
||||
private static function checkToken($token) {
|
||||
$data = explode('|', base64_decode(str_pad(strtr($token, '-_', '+/'), strlen($token) % 4, '=', STR_PAD_RIGHT)));
|
||||
list($login, $password, $until, $hash) = $data;
|
||||
|
||||
if($until < time())
|
||||
return false;
|
||||
if($hash != hash('sha256', $login.'|'.$password.'|'.$until.'|'.self::$secret))
|
||||
return false;
|
||||
|
||||
$user = DB::getQuery('main', 'SELECT `password` FROM `users` WHERE `login` = ?', $login);
|
||||
if($password != $user->password)
|
||||
return false;
|
||||
|
||||
self::updateOnline($login);
|
||||
|
||||
return $login;
|
||||
}
|
||||
|
||||
private static function updateOnline($login) {
|
||||
DB::getQuery('main', 'UPDATE `users` SET `online_dt` = ? WHERE `login` = ?', [time(), $login]);
|
||||
}
|
||||
}
|
||||
|
||||
User::init($config['user']);
|
36
engine/core/api/v1/authUser.php
Normal file
36
engine/core/api/v1/authUser.php
Normal file
@ -0,0 +1,36 @@
|
||||
<?php
|
||||
if($_SERVER['REQUEST_METHOD'] == 'POST') {
|
||||
if(!isset($_REQUEST['login'])) {
|
||||
$data = [
|
||||
'error' => true,
|
||||
'message' => 'Не передано поле login',
|
||||
];
|
||||
}
|
||||
elseif(!isset($_REQUEST['password'])) {
|
||||
$data = [
|
||||
'error' => true,
|
||||
'message' => 'Не передано поле password',
|
||||
];
|
||||
}
|
||||
elseif(!$token = User::auth($_REQUEST['login'], $_REQUEST['password'])) {
|
||||
$data = [
|
||||
'error' => true,
|
||||
'message' => 'Не вверно введены логин и/или пароль',
|
||||
];
|
||||
}
|
||||
else {
|
||||
$data = [
|
||||
'error' => false,
|
||||
'message' => 'Вход успешно совершен',
|
||||
'data' => [
|
||||
'token' => $token,
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
else {
|
||||
$data = [
|
||||
'error' => true,
|
||||
'message' => 'Только POST метод',
|
||||
];
|
||||
}
|
39
engine/core/api/v1/createUser.php
Normal file
39
engine/core/api/v1/createUser.php
Normal file
@ -0,0 +1,39 @@
|
||||
<?php
|
||||
if($_SERVER['REQUEST_METHOD'] == 'POST') {
|
||||
if(!isset($_REQUEST['login'])) {
|
||||
$data = [
|
||||
'error' => true,
|
||||
'message' => 'Не передано поле login',
|
||||
];
|
||||
}
|
||||
elseif(!isset($_REQUEST['password'])) {
|
||||
$data = [
|
||||
'error' => true,
|
||||
'message' => 'Не передано поле password',
|
||||
];
|
||||
}
|
||||
elseif(strlen($_REQUEST['password']) < 8) {
|
||||
$data = [
|
||||
'error' => true,
|
||||
'message' => 'Пароль должен иметь 8 символов минимум',
|
||||
];
|
||||
}
|
||||
elseif(!User::create($_REQUEST['login'], $_REQUEST['password'])) {
|
||||
$data = [
|
||||
'error' => true,
|
||||
'message' => 'Пользователь с таким логином уже сужествует',
|
||||
];
|
||||
}
|
||||
else {
|
||||
$data = [
|
||||
'error' => false,
|
||||
'message' => 'Пользователь создан',
|
||||
];
|
||||
}
|
||||
}
|
||||
else {
|
||||
$data = [
|
||||
'error' => true,
|
||||
'message' => 'Только POST метод',
|
||||
];
|
||||
}
|
27
engine/core/api/v1/deleteUser.php
Normal file
27
engine/core/api/v1/deleteUser.php
Normal file
@ -0,0 +1,27 @@
|
||||
<?php
|
||||
if($_SERVER['REQUEST_METHOD'] == 'DELETE') {
|
||||
if(!isset($_REQUEST['token'])) {
|
||||
$data = [
|
||||
'error' => true,
|
||||
'message' => 'Не передано поле token',
|
||||
];
|
||||
}
|
||||
elseif(!User::delete($_REQUEST['token'])) {
|
||||
$data = [
|
||||
'error' => true,
|
||||
'message' => 'Невалидный токен',
|
||||
];
|
||||
}
|
||||
else {
|
||||
$data = [
|
||||
'error' => false,
|
||||
'message' => 'Пользователь удален',
|
||||
];
|
||||
}
|
||||
}
|
||||
else {
|
||||
$data = [
|
||||
'error' => true,
|
||||
'message' => 'Только DELETE метод',
|
||||
];
|
||||
}
|
33
engine/core/api/v1/getUser.php
Normal file
33
engine/core/api/v1/getUser.php
Normal file
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
if($_SERVER['REQUEST_METHOD'] == 'GET') {
|
||||
if(!isset($_REQUEST['login'])) {
|
||||
$data = [
|
||||
'error' => true,
|
||||
'message' => 'Не передано поле login',
|
||||
];
|
||||
}
|
||||
elseif(!$user = User::get($_REQUEST['login'])) {
|
||||
$data = [
|
||||
'error' => true,
|
||||
'message' => 'Пользователь не существует',
|
||||
];
|
||||
}
|
||||
else {
|
||||
$data = [
|
||||
'error' => false,
|
||||
'data' => [
|
||||
'id' => $user->id,
|
||||
'login' => $user->login,
|
||||
'info' => $user->info,
|
||||
'reg_dt' => $user->reg_dt,
|
||||
'online_dt' => $user->online_dt,
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
else {
|
||||
$data = [
|
||||
'error' => true,
|
||||
'message' => 'Только метод GET',
|
||||
];
|
||||
}
|
34
engine/core/api/v1/updateUserInfo.php
Normal file
34
engine/core/api/v1/updateUserInfo.php
Normal file
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
if($_SERVER['REQUEST_METHOD'] == 'PATCH') {
|
||||
if(!isset($_REQUEST['token'])) {
|
||||
$data = [
|
||||
'error' => true,
|
||||
'message' => 'Не передано поле token',
|
||||
];
|
||||
}
|
||||
elseif(!isset($_REQUEST['newInfo'])) {
|
||||
$data = [
|
||||
'error' => true,
|
||||
'message' => 'Не передано поле newInfo',
|
||||
];
|
||||
}
|
||||
elseif(!User::updateInfo($_REQUEST['token'], $_REQUEST['newInfo'])) {
|
||||
$data = [
|
||||
'error' => true,
|
||||
'message' => 'Невалидный токен',
|
||||
];
|
||||
}
|
||||
else {
|
||||
$data = [
|
||||
'error' => false,
|
||||
'message' => 'Информация обновлена',
|
||||
];
|
||||
}
|
||||
}
|
||||
else {
|
||||
$data = [
|
||||
'error' => true,
|
||||
'message' => 'Только PATCH метод',
|
||||
];
|
||||
}
|
||||
|
Reference in New Issue
Block a user