completed

This commit is contained in:
Stepan 2025-12-25 00:02:39 +01:00
parent b0a3a3bb1e
commit 97cd878dd0
16 changed files with 534 additions and 204 deletions

30
add_photo.php Normal file
View File

@ -0,0 +1,30 @@
<?php
require_once __DIR__ . "/functions.php";
middlewareAuthorized("admin");
function error_redirect($message) {
$error = urlencode($message);
header("Location: new_photo.php?error=$error");
exit;
}
$is_file_uploaded = isset($_FILES['file']) && !empty($_FILES['file']['tmp_name']);
$category = $_POST['category_id'] ?? '';
$description = $_POST['description'] ?? '';
if(empty($category) || empty($description)) {
error_redirect("Description or category empty");
}
$category = intval($category);
if(!$is_file_uploaded)
error_redirect("File is not uploaded");
$tmpPath = $_FILES['file']['tmp_name'];
$imageType = exif_imagetype($tmpPath);
if($imageType !== IMAGETYPE_PNG)
error_redirect("File is not png format");
$path = upload_file($_FILES['file'], "photos/");
insertPhoto($_SESSION['id_user'], $category, $path, $description);
header("Location: new_photo.php?success=true");

34
admins.php Normal file
View File

@ -0,0 +1,34 @@
<?php
require_once __DIR__ . "/functions.php";
middlewareAuthorized("admin");
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Admin Page</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-sRIl4kxILFvY47J16cr9ZwB07vP4J8+LH7qKQnuqkuIAvNWLzeN8tE5YBujZqJLB" crossorigin="anonymous">
<style>
.btn-toolbar > * {
margin-right: 20px;
}
</style>
</head>
<body>
<div class="container">
<h1>Admin Page</h1>
<div class="d-flex">
<div class="btn-toolbar">
<div class="btn-group mr-2">
<a href="new_photo.php" class="btn btn-primary" role="button">New Photo</a>
</div>
<div class="btn-group">
<a href="logout.php" class="btn btn-danger" role="button">Logout</a>
</div>
</div>
</div>
</div>
</body>
</html>

View File

@ -1,5 +1,6 @@
<?php
declare(strict_types=1);
session_start();
const PARAMS = [
"HOST" => 'localhost',
@ -9,6 +10,8 @@ const PARAMS = [
"CHARSET" => 'utf8mb4'
];
const MEDIA_ROOT = __DIR__ . "/media/";
$dsn = "mysql:host=" . PARAMS['HOST'] . ";dbname=" . PARAMS['DB'] . ";charset=" . PARAMS['CHARSET'];
$pdoOptions = [

53
data.txt Normal file
View File

@ -0,0 +1,53 @@
array(3) {
[0]=>
array(7) {
["username"]=>
string(8) "useraxel"
["name"]=>
string(4) "Axel"
["email"]=>
string(18) "useraxel@photo.com"
["level"]=>
string(8) "reporter"
["age"]=>
int(25)
["password"]=>
string(18) "useraxel1766616750"
["hashed_password"]=>
string(60) "$2y$12$hYQWEVJC0OjEc4ugnZNh2OZIb80qeQxjcBqTHX1wbULcxYXpr.Rbq"
}
[1]=>
array(7) {
["username"]=>
string(9) "userchris"
["name"]=>
string(5) "Chris"
["email"]=>
string(19) "userchris@photo.com"
["level"]=>
string(5) "guest"
["age"]=>
int(32)
["password"]=>
string(19) "userchris1766616751"
["hashed_password"]=>
string(60) "$2y$12$3UlXEjtlF58v2tV0JelOdez0VwC0IreO0oRdHTZz7mj.s2Llwx7gK"
}
[2]=>
array(7) {
["username"]=>
string(7) "usertom"
["name"]=>
string(3) "Tom"
["email"]=>
string(17) "usertom@photo.com"
["level"]=>
string(5) "admin"
["age"]=>
int(31)
["password"]=>
string(17) "usertom1766616751"
["hashed_password"]=>
string(60) "$2y$12$C0wzZ5hdTDLReiIt2hX72ewNCUQGX2LYFihvCoAA/cAqjnNuQAeo6"
}
}

View File

@ -21,22 +21,33 @@ function connectDatabase(string $dsn, array $pdoOptions): PDO
return $pdo;
}
function getCategories() {
global $pdo;
$stmt = $pdo->prepare("SELECT * FROM categories ORDER BY name ASC");
$stmt->execute();
$categories = $stmt->fetchAll(PDO::FETCH_ASSOC);
return $categories;
}
function parseCategories(string $cat_string)
{
$cat_string = trim($cat_string);
$cats = explode(" ", $cat_string);
$filtered_cats = array_filter($cats, function($cat) {
if(mb_strlen($cat) <= 4)
$filtered_cats = array_filter($cats, function ($cat) {
if (mb_strlen($cat) <= 4)
return false;
return(ctype_alnum($cat));
return (ctype_alnum($cat));
});
return $filtered_cats;
}
function insertCategories(array $cats) {
function insertCategories(array $cats)
{
global $pdo;
try {
@ -51,21 +62,213 @@ function insertCategories(array $cats) {
}
$pdo->commit();
}
catch (Exception $e) {
} catch (Exception $e) {
$pdo->rollBack();
throw $e;
}
}
function insertError(string $username, string $password) {
global $pdo;
class User {
function createUser() {
$stmt = $pdo->prepare("INSERT INTO errors (username, password) VALUES (:username, :password)");
$stmt->execute([
':username' => $username,
':password' => $password
]);
}
function insertLog(int $userid) {
global $pdo;
$stmt = $pdo->prepare("INSERT INTO logs (user_id) VALUES (:user_id)");
$stmt->execute([
':user_id' => $userid
]);
}
function insertPhoto(int $user_id, int $category_id, string $file, $description) {
global $pdo;
$stmt = $pdo->prepare("INSERT INTO photos (user_id, category_id, file, description) VALUES (:user_id, :category_id, :file, :description)");
$stmt->execute([
':user_id' => $user_id,
':category_id' => $category_id,
':file' => $file,
':description' => $description
]);
}
class ValidationError extends Exception { }
class User
{
private ?int $id;
public string $username;
public string $hashed_password;
public int $age;
public string $email;
public string $level;
const LEVELS = ['admin', 'reporter', 'guest'];
public function __construct(int $id, string $username, string $hashed_password, int $age, string $email, string $level) {
$this->id = $id;
$this->username = $username;
$this->hashed_password = $hashed_password;
$this->age = $age;
$this->email = $email;
$this->level = $level;
}
function createUserStmt() {
public function getId() {
return $this->id;
}
function createUsers() {
static function authorize(string $username, string $password) {
global $pdo;
$stmt = $pdo->prepare("SELECT * FROM users WHERE username = :username");
$stmt->execute([
':username' => $username
]);
$user_arr = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$user_arr) {
throw new ValidationError("User not found");
}
if (password_verify($password, $user_arr['password'])) {
return new User(
$user_arr['id'],
$user_arr['username'],
$user_arr['password'],
$user_arr['age'],
$user_arr['email'],
$user_arr['level']
);
}
throw new ValidationError("Password is not correct");
}
static function createUser(string $username, string $password, int $age, string $name, string $email, string $level) {
global $pdo;
$stmt = $pdo->prepare("INSERT INTO users (username, password, age, email, level) VALUES (:username, :password, :age, :email, :level)");
$hashed_password = password_hash($password, PASSWORD_BCRYPT);
$stmt->execute([
':username' => $username,
':password' => $hashed_password,
':age' => $age,
':email' => $email,
':level' => $level,
]);
$id = $pdo->lastInsertId();
return new User($id, $username, $hashed_password, $age, $email, $level);
}
}
function createRandomUsers() {
$names = ['ChrIS2','JohHn2','3toM','rAY','AxEl', '1bOraT'];
$random_level = array_values(User::LEVELS);
shuffle($random_level);
$mapped_names = array_map(function($name) {
$result = preg_replace('/[^a-zA-Z]/', '', $name);
$result = strtolower($result);
return ucfirst($result);
}, $names);
$used_name_ids = [];
$users_array = array_map(function($level) use ($mapped_names, &$used_name_ids) {
$random_name_id = array_rand($mapped_names);
$random_name = $mapped_names[$random_name_id];
$suffix_username = "";
if(in_array($random_name_id, $used_name_ids)) {
$suffix_username = strval(rand(10, 200));
}
$used_name_ids[] = $random_name_id;
$username = 'user' . strtolower($random_name) . $suffix_username;
$email = $username . '@photo.com';
$password = $username . time();
$hashed_password = password_hash($password, PASSWORD_BCRYPT);
$age = rand(18, 47);
$user = array(
'username' => $username,
'name' => $random_name,
'email' => $email,
'level' => $level,
'age' => $age,
'password' => $password,
'hashed_password' => $hashed_password
);
return $user;
}, $random_level);
return $users_array;
}
function login(User $user) {
$_SESSION['id_user'] = $user->getId();
$_SESSION['username'] = $user->username;
$_SESSION['level'] = $user->level;
}
function logout() {
unset($_SESSION['id_user']);
unset($_SESSION['username']);
unset($_SESSION['level']);
}
function middlewareAuthorized(?string $role = null) {
if(!isset($_SESSION['id_user']))
header("Location: index.php");
if(!empty($role)) {
if($_SESSION['level'] != $role) {
http_response_code(403);
echo "403 - Permission Denied";
exit;
}
}
}
/**
* Upload file to server
* @param array $file
* @param string $subfolder_name like 'products/'
* @return string|false
*/
function upload_file($file, $subfolder_name) {
if (isset($file) && $file['error'] === UPLOAD_ERR_OK) {
$uploadDir = MEDIA_ROOT;
// Create new unique filename
$fileName = pathinfo($file['name'], PATHINFO_FILENAME);
$fileExtension = pathinfo($file['name'], PATHINFO_EXTENSION);
$newFileName = time() . "-" . rand(100, 500) . '-' . $_SESSION['id_user'] . '.' . $fileExtension;
// media/{subfolder_name}/{new_file.png}
$uploadFile = $uploadDir . $subfolder_name . $newFileName;
$filepath_db = $subfolder_name . $newFileName;
// Get file type
$fileType = mime_content_type($file['tmp_name']);
// if subfolder is not exists
if (!is_dir($uploadDir . $subfolder_name)) {
mkdir($uploadDir . $subfolder_name, 0775, true);
}
// Upload file to server
if (strpos($fileType, 'image') === 0) {
if (move_uploaded_file($file['tmp_name'], $uploadFile)) {
return $filepath_db;
} else {
return false;
}
}
}
return false;
}

35
index.php Normal file
View File

@ -0,0 +1,35 @@
<?php
$error_message = $_GET['error'] ?? '';
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Login</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-sRIl4kxILFvY47J16cr9ZwB07vP4J8+LH7qKQnuqkuIAvNWLzeN8tE5YBujZqJLB" crossorigin="anonymous">
</head>
<body>
<div class="container p-3">
<form action="login.php" method="post">
<?php if(!empty($error_message)): ?>
<div class="alert alert-danger" role="alert">
<?= $error_message ?>
</div>
<?php endif; ?>
<div class="form-group mb-3">
<label for="username">Username</label>
<input type="text" class="form-control" name="username" id="username" placeholder="Enter username">
</div>
<div class="form-group mb-3">
<label for="password">Password</label>
<input type="password" class="form-control" name="password" id="password" placeholder="Password">
</div>
<button type="submit" class="btn btn-primary">Sign In</button>
</form>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/js/bootstrap.bundle.min.js" integrity="sha384-FKyoEForCGlyvwx9Hj09JcYn3nv7wiPVlz7YYwJrWVcXK/BmnVDxM+D2scQbITxI" crossorigin="anonymous"></script>
</body>
</html>

34
login.php Normal file
View File

@ -0,0 +1,34 @@
<?php
require_once __DIR__ . '/functions.php';
function error_redirect($message) {
$error = urlencode($message);
header("Location: index.php?error=$error");
exit;
}
$username = $_POST['username'] ?? '';
$password = $_POST['password'] ?? '';
if(empty($username) || empty($password)) {
error_redirect("You username/password is empty");
}
try {
$user = User::authorize($username, $password);
login($user);
insertLog($user->getId());
if($user->level == 'admin')
header("Location: admins.php");
else
header("Location: photos.php");
}
catch (ValidationError $ex) {
insertError($username, $password);
error_redirect($ex->getMessage());
}
catch (Exception $ex) {
error_redirect("500 - Server error");
}
echo "AAA";

4
logout.php Normal file
View File

@ -0,0 +1,4 @@
<?php
require_once __DIR__ . "/functions.php";
logout();
header("Location: index.php");

Binary file not shown.

After

Width:  |  Height:  |  Size: 541 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 538 KiB

57
new_photo.php Normal file
View File

@ -0,0 +1,57 @@
<?php
require_once __DIR__ . "/functions.php";
middlewareAuthorized("admin");
$error_message = $_GET['error'] ?? '';
$is_success = isset($_GET['success']);
$categories = getCategories();
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Add Photo</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-sRIl4kxILFvY47J16cr9ZwB07vP4J8+LH7qKQnuqkuIAvNWLzeN8tE5YBujZqJLB" crossorigin="anonymous">
</head>
<body>
<div class="container">
<h1>Add Photo</h1>
<form action="add_photo.php" method="post" enctype="multipart/form-data">
<?php if(!empty($error_message)): ?>
<div class="alert alert-danger" role="alert">
<?= $error_message ?>
</div>
<?php endif; ?>
<?php if($is_success): ?>
<div class="alert alert-success" role="alert">
File was uploaded successfully
</div>
<?php endif; ?>
<div class="mb-3">
<div class="mb-3">
<label for="file" class="form-label">Image</label>
<input class="form-control" type="file" id="file" name="file" accept="image/png">
</div>
<div class="mb-3">
<label for="category_id" class="form-label">Category</label>
<select class="form-select" name="category_id" id="category_id">
<option selected>Open to select category</option>
<?php foreach ($categories as $cat): ?>
<option value="<?= $cat['id'] ?>"><?= $cat['name'] ?></option>
<?php endforeach; ?>
</select>
</div>
<div>
<label for="description" class="form-label">Description</label>
<textarea class="form-control" id="description" name="description" rows="3"></textarea>
</div>
</div>
<button type="submit" class="btn btn-primary">Add Photo</button>
</form>
</div>
</body>
</html>

23
photos.php Normal file
View File

@ -0,0 +1,23 @@
<?php
require_once __DIR__ . "/functions.php";
middlewareAuthorized();
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Photos</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-sRIl4kxILFvY47J16cr9ZwB07vP4J8+LH7qKQnuqkuIAvNWLzeN8tE5YBujZqJLB" crossorigin="anonymous">
</head>
<body>
<div class="container">
<h1>Welcome to our site</h1>
<div>
<a href="logout.php" class="btn btn-danger" role="button">Logout</a>
</div>
</div>
</body>
</html>

10
random_users.php Normal file
View File

@ -0,0 +1,10 @@
<?php require_once __DIR__ . "/functions.php";
$random_users = createRandomUsers();
var_dump($random_users);
ob_start();
var_dump($random_users);
$output = ob_get_clean();
file_put_contents('data.txt', $output);

View File

@ -1,3 +1,18 @@
1. Umesto `getCategories` bolje nazvati funkciju `parseCategories` zato sta `get...` podrazumeva samo dobijanje podataka (npr., iz db), a ne odbradu string-a.
> U fajlu category.php pozvati funkciju getCategories. Ovu funkciju napisati u functions.php fajlu. Funkcija getCategories STRIKTNO
prima promenljivu $cat = " na2t5u25re spo12r54t funn82y cake2! 8sea au#!tumn!"; i vraća niz koji sadrži reči koje se sastoje SAMO iz brojeva i slova i čija je dužina podatka veća od 4.
2. `createUsers` osim toga, sta kreira korisnika rade parsiranje iz string-ova i autogenerisanje random podataka šta predstavlja **God Function** i uništava **Single Responsibility Principle**.
Bolje uraditi klas `User` koji će imati `createUserStmp`, `createUser` i `createUsers` koji uzimaju prototip objekata od klasa User.
Bolje uraditi klas `User` koji će imati `createUser` koji uzimaju prototip objekata od klasa User. A za kreiranje random korisnika biće funkcija izvan `createRandomUsers`
> Kreirati funkciju createUsers i smestiti je u fajl functions.php. Pozvati ovu funkciju u fajlu users.php. Niz $names =
['ChrIS2','JohHn2','3toM','rAY','AxEl', '1bOraT'] i niz $level = ['admin','reporter','guest'] smestiti u fajl config.php. Funkcija
createUsers treba striktno da prima odgovarajuće parametre i da striktno vrati niz sa 3 korisnika. Niz users treba da poseduje 3
podniza sa indeksima: username, password, hashed_password, age, name, email, level. Primenom funkcije array_map sve
vrednosti u nizu names promeniti tako da se uklone svi brojevi i da samo prvi karakter bude veliko slovo
3. Isto iz drugog koraka, bolje uraditi klasu `User` i vratiti umesto asociativnog niza prototip klasa `User` sa svima metodami za odbradu i poljami.
3. Bolje logiku za `User` ostaviti samo u klasu, kreirati `LEVELS` konstantu u klase nego u config.php koji odgovara za sav aplikaciju.
4. Nemamo ponavljanjih imena (*'ChrIS2','JohHn2','3toM','rAY','AxEl', '1bOraT'*) i zato taj uslov nikada nece biti ispunjen.
> Ukoliko je već korišćeno neko ime u nizu, dodati slučajni broj između 10 i 200 na kraj username-a (na primer useraxel123).

22
users.php Normal file
View File

@ -0,0 +1,22 @@
<?php require_once __DIR__ . "/random_users.php";
try {
$pdo->beginTransaction();
foreach ($random_users as $rand_user) {
User::createUser(
$rand_user['username'],
$rand_user['password'],
$rand_user['age'],
$rand_user['name'],
$rand_user['email'],
$rand_user['level']
);
}
$pdo->commit();
}
catch(Exception $ex) {
$pdo->rollBack();
print($ex->getMessage());
}

View File

@ -1,193 +0,0 @@
-- phpMyAdmin SQL Dump
-- version 5.2.3
-- https://www.phpmyadmin.net/
--
-- Хост: localhost
-- Время создания: Дек 24 2025 г., 13:06
-- Версия сервера: 12.0.2-MariaDB
-- Версия PHP: 8.4.14
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
START TRANSACTION;
SET time_zone = "+00:00";
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8mb4 */;
--
-- База данных: `web_prog_task_15`
--
-- --------------------------------------------------------
--
-- Структура таблицы `categories`
--
CREATE TABLE `categories` (
`id` int(11) NOT NULL,
`name` varchar(50) NOT NULL,
`code` int(11) DEFAULT 0,
`date_time_added` datetime DEFAULT current_timestamp()
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
--
-- Дамп данных таблицы `categories`
--
INSERT INTO `categories` (`id`, `name`, `code`, `date_time_added`) VALUES
(1, 'nature', 7106, '2025-12-23 12:53:25'),
(2, 'sport', 3419, '2025-12-23 12:53:25'),
(3, 'funny', 4055, '2025-12-23 12:53:25');
-- --------------------------------------------------------
--
-- Структура таблицы `errors`
--
CREATE TABLE `errors` (
`id` int(11) NOT NULL,
`username` varchar(50) NOT NULL,
`password` varchar(255) NOT NULL,
`date_time` datetime DEFAULT current_timestamp()
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- --------------------------------------------------------
--
-- Структура таблицы `logs`
--
CREATE TABLE `logs` (
`id` int(11) NOT NULL,
`user_id` int(11) NOT NULL,
`date_time_added` datetime DEFAULT current_timestamp()
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- --------------------------------------------------------
--
-- Структура таблицы `photos`
--
CREATE TABLE `photos` (
`id` int(11) NOT NULL,
`user_id` int(11) NOT NULL,
`category_id` int(11) NOT NULL,
`file` varchar(255) NOT NULL,
`description` text DEFAULT NULL,
`date_time_added` datetime DEFAULT current_timestamp()
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- --------------------------------------------------------
--
-- Структура таблицы `users`
--
CREATE TABLE `users` (
`id` int(11) NOT NULL,
`username` varchar(50) NOT NULL,
`password` varchar(255) NOT NULL,
`age` int(11) NOT NULL,
`email` varchar(100) NOT NULL,
`level` enum('admin','reporter','guest') NOT NULL,
`date_time_added` datetime DEFAULT current_timestamp()
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
--
-- Индексы сохранённых таблиц
--
--
-- Индексы таблицы `categories`
--
ALTER TABLE `categories`
ADD PRIMARY KEY (`id`);
--
-- Индексы таблицы `errors`
--
ALTER TABLE `errors`
ADD PRIMARY KEY (`id`);
--
-- Индексы таблицы `logs`
--
ALTER TABLE `logs`
ADD PRIMARY KEY (`id`),
ADD KEY `user_id` (`user_id`);
--
-- Индексы таблицы `photos`
--
ALTER TABLE `photos`
ADD PRIMARY KEY (`id`),
ADD KEY `user_id` (`user_id`),
ADD KEY `category_id` (`category_id`);
--
-- Индексы таблицы `users`
--
ALTER TABLE `users`
ADD PRIMARY KEY (`id`);
--
-- AUTO_INCREMENT для сохранённых таблиц
--
--
-- AUTO_INCREMENT для таблицы `categories`
--
ALTER TABLE `categories`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=4;
--
-- AUTO_INCREMENT для таблицы `errors`
--
ALTER TABLE `errors`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
--
-- AUTO_INCREMENT для таблицы `logs`
--
ALTER TABLE `logs`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
--
-- AUTO_INCREMENT для таблицы `photos`
--
ALTER TABLE `photos`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
--
-- AUTO_INCREMENT для таблицы `users`
--
ALTER TABLE `users`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
--
-- Ограничения внешнего ключа сохраненных таблиц
--
--
-- Ограничения внешнего ключа таблицы `logs`
--
ALTER TABLE `logs`
ADD CONSTRAINT `logs_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`);
--
-- Ограничения внешнего ключа таблицы `photos`
--
ALTER TABLE `photos`
ADD CONSTRAINT `photos_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`),
ADD CONSTRAINT `photos_ibfk_2` FOREIGN KEY (`category_id`) REFERENCES `categories` (`id`);
COMMIT;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;