diff --git a/.gitignore b/.gitignore index 0557da4..3f280c4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ .history/ -backend/config/config.php \ No newline at end of file +backend/config/config.php +backend/vendor/ \ No newline at end of file diff --git a/backend/README.md b/backend/README.md index 5b6d351..eaef634 100644 --- a/backend/README.md +++ b/backend/README.md @@ -4,6 +4,8 @@ You need PHP installed (e.g. `sudo apt install php` on Ubuntu) +Then run: + `git clone https://github.com/19pdh/harcdzielnia.app` `cd backend/config` @@ -12,12 +14,118 @@ Create file `config.php` and fill it like `config.template.php`. ## Rewrites -Basically you can access API at `routes/.php`, but you should rewrite endpoints on your own with `id` param in URL. +Basically you can access API at `routes/.php` and use basic GET params, but you should rewrite endpoints on your own. Example for Apache: ``` -RewriteRule items/([0-9]+)$ routes/item.php?id=$1 +RewriteRule items$ routes/public/items.php +RewriteRule items/([0-9]+)$ routes/public/item.php?id=$1 +RewriteRule items/([0-9]+)/handed$ routes/public/item-handed?id=$1 +RewriteRule items/add$ routes/public/add-item.php + +RewriteRule items/unapproved$ routes/management/unapproved-items.php +RewriteRule items/([0-9]+)/details$ routes/management/item-details.php?id=$1 +RewriteRule items/create$ routes/management/create-item.php +RewriteRule items/([0-9]+)/approve$ routes/management/approve-item.php?id=$1 +RewriteRule items/([0-9]+)/delete$ routes/management/delete-item.php?id=$1 +RewriteRule items/([0-9]+)/hide$ routes/management/hide-item.php?id=$1 + +RewriteRule users$ routes/admin/users.php +RewriteRule users/add$ routes/admin/add-user.php +RewriteRule users/([0-9]+)/delete$ routes/admin/delete-user.php?id=$1 + +RewriteRule user$ routes/auth/user.php +RewriteRule user/login$ routes/auth/login.php +RewriteRule user/logout$ routes/auth/logout.php +RewriteRule user/reset-password$ routes/auth/reset-password.php +RewriteRule user/change-password$ routes/auth/change-password.php ``` -(`/items/1 -> /routes/item.php?id=1`) +(e.g. `/items/1 -> /routes/item.php?id=1`) + +## API Endpoints + +### Public + +**GET** `/items` - list items +**GET** `/items/ID` - detailed info about item with ID +**POST** `/items/ID/handed` - hide item on website (item was handed over) - sending confirmation link via email +|Name|Description| +|---------|---------| +| email| E-mail used in adding item form | +| token _(optional)_| Token from email (probably placed in GET query param) | + +**POST** `/items/add` - add new item +|Name|Description| +|---------|---------| +|name|Item name| +|description|Item description| +|image **(file)**|Item image| +|order_type|Item order type (1/2/3)| +|contact_info| Public contact info of item owner| +|email|Item owner e-mail for system notifications and authentication| + +### Management + +**GET** `/items/unapproved` - list unapproved items +**GET** `/items/ID/details` - detailed info (and owner email) about item with ID +**POST** `items/create` - create new item (bypassing approve process) +|Name|Description| +|---------|---------| +|name|Item name| +|description|Item description| +|image **(file)**|Item image| +|order_type|Item order type (1/2/3)| +|contact_info|Public contact info of item owner| +|email|Item owner e-mail for system notifications and authentication| +|csrf|CSRF token from cookie "csrf"| +**POST** `/items/ID/approve` - approve new item +|Name|Description| +|---------|---------| +|csrf|CSRF token from cookie "csrf"| +**POST** `/items/ID/delete` - delete existing item +|Name|Description| +|---------|---------| +|csrf|CSRF token from cookie "csrf"| +**POST** `/items/ID/hide` - hide existing item on website (bypass email confirmation) +|Name|Description| +|---------|---------| +|csrf|CSRF token from cookie "csrf"| + +### User + +**GET** `/user` - get currently logged in user data +**POST** `/user/login` - user login +|Name|Description| +|---------|---------| +|email|User e-mail| +|password|User password| +|csrf|CSRF token from cookie "csrf"| +**GET** `/user/logout` - user logout +**POST** `/user/change-password` - change user password +|Name|Description| +|---------|---------| +|csrf|CSRF token from cookie "csrf"| +|password|New user password| +|old-password|Old user password| +**POST** `/user/reset-password` - reset user password +|Name|Description| +|---------|---------| +|csrf|CSRF token from cookie "csrf"| +|email|User email| + +### Admin + +**GET** `/users` - list users +**POST** `/users/add` - add new user (sending default password via email) +|Name|Description| +|---------|---------| +|name|User name| +|permissions|User permissions (0/1/2/3)| +|email|User email| +|csrf|CSRF token from cookie "csrf"| +**POST** `/users/ID/delete` - delete user with ID +|Name|Description| +|---------|---------| +|csrf|CSRF token from cookie "csrf"| diff --git a/backend/composer.json b/backend/composer.json new file mode 100644 index 0000000..1bd7d9a --- /dev/null +++ b/backend/composer.json @@ -0,0 +1,5 @@ +{ + "require": { + "cloudinary/cloudinary_php": "^2.7" + } +} diff --git a/backend/composer.lock b/backend/composer.lock new file mode 100644 index 0000000..14e2470 --- /dev/null +++ b/backend/composer.lock @@ -0,0 +1,887 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "This file is @generated automatically" + ], + "content-hash": "e63d76f163111b5f8d3f35abbd1ed2cf", + "packages": [ + { + "name": "cloudinary/cloudinary_php", + "version": "2.7.0", + "source": { + "type": "git", + "url": "https://github.com/cloudinary/cloudinary_php.git", + "reference": "c231bcc4bd27bd5dbf19739fb30a4f57a5483b78" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/cloudinary/cloudinary_php/zipball/c231bcc4bd27bd5dbf19739fb30a4f57a5483b78", + "reference": "c231bcc4bd27bd5dbf19739fb30a4f57a5483b78", + "shasum": "" + }, + "require": { + "ext-json": "*", + "guzzlehttp/guzzle": "^6|^7", + "monolog/monolog": "^1|^2", + "php": ">=5.6.0", + "psr/log": "^1|^2|^3", + "shrikeh/teapot": "^1|^2" + }, + "require-dev": { + "consolidation/robo": "~1", + "ext-dom": "*", + "ext-libxml": "*", + "ext-zip": "*", + "friendsofphp/php-cs-fixer": "*", + "phpmd/phpmd": "*", + "phpunit/phpunit": "^5", + "squizlabs/php_codesniffer": "3.*" + }, + "type": "library", + "autoload": { + "classmap": [ + "src" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Cloudinary", + "homepage": "https://github.com/cloudinary/cloudinary_php/graphs/contributors" + } + ], + "description": "Cloudinary PHP SDK", + "homepage": "https://github.com/cloudinary/cloudinary_php", + "keywords": [ + "cdn", + "cloud", + "cloudinary", + "image management", + "sdk" + ], + "time": "2022-05-23T08:02:03+00:00" + }, + { + "name": "guzzlehttp/guzzle", + "version": "7.4.2", + "source": { + "type": "git", + "url": "https://github.com/guzzle/guzzle.git", + "reference": "ac1ec1cd9b5624694c3a40be801d94137afb12b4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/ac1ec1cd9b5624694c3a40be801d94137afb12b4", + "reference": "ac1ec1cd9b5624694c3a40be801d94137afb12b4", + "shasum": "" + }, + "require": { + "ext-json": "*", + "guzzlehttp/promises": "^1.5", + "guzzlehttp/psr7": "^1.8.3 || ^2.1", + "php": "^7.2.5 || ^8.0", + "psr/http-client": "^1.0", + "symfony/deprecation-contracts": "^2.2 || ^3.0" + }, + "provide": { + "psr/http-client-implementation": "1.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.4.1", + "ext-curl": "*", + "php-http/client-integration-tests": "^3.0", + "phpunit/phpunit": "^8.5.5 || ^9.3.5", + "psr/log": "^1.1 || ^2.0 || ^3.0" + }, + "suggest": { + "ext-curl": "Required for CURL handler support", + "ext-intl": "Required for Internationalized Domain Name (IDN) support", + "psr/log": "Required for using the Log middleware" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "7.4-dev" + } + }, + "autoload": { + "files": [ + "src/functions_include.php" + ], + "psr-4": { + "GuzzleHttp\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "Jeremy Lindblom", + "email": "jeremeamia@gmail.com", + "homepage": "https://github.com/jeremeamia" + }, + { + "name": "George Mponos", + "email": "gmponos@gmail.com", + "homepage": "https://github.com/gmponos" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://github.com/sagikazarmark" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" + } + ], + "description": "Guzzle is a PHP HTTP client library", + "keywords": [ + "client", + "curl", + "framework", + "http", + "http client", + "psr-18", + "psr-7", + "rest", + "web service" + ], + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/guzzle", + "type": "tidelift" + } + ], + "time": "2022-03-20T14:16:28+00:00" + }, + { + "name": "guzzlehttp/promises", + "version": "1.5.1", + "source": { + "type": "git", + "url": "https://github.com/guzzle/promises.git", + "reference": "fe752aedc9fd8fcca3fe7ad05d419d32998a06da" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/promises/zipball/fe752aedc9fd8fcca3fe7ad05d419d32998a06da", + "reference": "fe752aedc9fd8fcca3fe7ad05d419d32998a06da", + "shasum": "" + }, + "require": { + "php": ">=5.5" + }, + "require-dev": { + "symfony/phpunit-bridge": "^4.4 || ^5.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.5-dev" + } + }, + "autoload": { + "files": [ + "src/functions_include.php" + ], + "psr-4": { + "GuzzleHttp\\Promise\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" + } + ], + "description": "Guzzle promises library", + "keywords": [ + "promise" + ], + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/promises", + "type": "tidelift" + } + ], + "time": "2021-10-22T20:56:57+00:00" + }, + { + "name": "guzzlehttp/psr7", + "version": "2.2.1", + "source": { + "type": "git", + "url": "https://github.com/guzzle/psr7.git", + "reference": "c94a94f120803a18554c1805ef2e539f8285f9a2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/c94a94f120803a18554c1805ef2e539f8285f9a2", + "reference": "c94a94f120803a18554c1805ef2e539f8285f9a2", + "shasum": "" + }, + "require": { + "php": "^7.2.5 || ^8.0", + "psr/http-factory": "^1.0", + "psr/http-message": "^1.0", + "ralouphie/getallheaders": "^3.0" + }, + "provide": { + "psr/http-factory-implementation": "1.0", + "psr/http-message-implementation": "1.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.4.1", + "http-interop/http-factory-tests": "^0.9", + "phpunit/phpunit": "^8.5.8 || ^9.3.10" + }, + "suggest": { + "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.2-dev" + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Psr7\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "George Mponos", + "email": "gmponos@gmail.com", + "homepage": "https://github.com/gmponos" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://github.com/sagikazarmark" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://sagikazarmark.hu" + } + ], + "description": "PSR-7 message implementation that also provides common utility methods", + "keywords": [ + "http", + "message", + "psr-7", + "request", + "response", + "stream", + "uri", + "url" + ], + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/psr7", + "type": "tidelift" + } + ], + "time": "2022-03-20T21:55:58+00:00" + }, + { + "name": "monolog/monolog", + "version": "2.6.0", + "source": { + "type": "git", + "url": "https://github.com/Seldaek/monolog.git", + "reference": "247918972acd74356b0a91dfaa5adcaec069b6c0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/247918972acd74356b0a91dfaa5adcaec069b6c0", + "reference": "247918972acd74356b0a91dfaa5adcaec069b6c0", + "shasum": "" + }, + "require": { + "php": ">=7.2", + "psr/log": "^1.0.1 || ^2.0 || ^3.0" + }, + "provide": { + "psr/log-implementation": "1.0.0 || 2.0.0 || 3.0.0" + }, + "require-dev": { + "aws/aws-sdk-php": "^2.4.9 || ^3.0", + "doctrine/couchdb": "~1.0@dev", + "elasticsearch/elasticsearch": "^7 || ^8", + "ext-json": "*", + "graylog2/gelf-php": "^1.4.2", + "guzzlehttp/guzzle": "^7.4", + "guzzlehttp/psr7": "^2.2", + "mongodb/mongodb": "^1.8", + "php-amqplib/php-amqplib": "~2.4 || ^3", + "php-console/php-console": "^3.1.3", + "phpspec/prophecy": "^1.15", + "phpstan/phpstan": "^0.12.91", + "phpunit/phpunit": "^8.5.14", + "predis/predis": "^1.1", + "rollbar/rollbar": "^1.3 || ^2 || ^3", + "ruflin/elastica": "^7", + "swiftmailer/swiftmailer": "^5.3|^6.0", + "symfony/mailer": "^5.4 || ^6", + "symfony/mime": "^5.4 || ^6" + }, + "suggest": { + "aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB", + "doctrine/couchdb": "Allow sending log messages to a CouchDB server", + "elasticsearch/elasticsearch": "Allow sending log messages to an Elasticsearch server via official client", + "ext-amqp": "Allow sending log messages to an AMQP server (1.0+ required)", + "ext-curl": "Required to send log messages using the IFTTTHandler, the LogglyHandler, the SendGridHandler, the SlackWebhookHandler or the TelegramBotHandler", + "ext-mbstring": "Allow to work properly with unicode symbols", + "ext-mongodb": "Allow sending log messages to a MongoDB server (via driver)", + "ext-openssl": "Required to send log messages using SSL", + "ext-sockets": "Allow sending log messages to a Syslog server (via UDP driver)", + "graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server", + "mongodb/mongodb": "Allow sending log messages to a MongoDB server (via library)", + "php-amqplib/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib", + "php-console/php-console": "Allow sending log messages to Google Chrome", + "rollbar/rollbar": "Allow sending log messages to Rollbar", + "ruflin/elastica": "Allow sending log messages to an Elastic Search server" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.x-dev" + } + }, + "autoload": { + "psr-4": { + "Monolog\\": "src/Monolog" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "https://seld.be" + } + ], + "description": "Sends your logs to files, sockets, inboxes, databases and various web services", + "homepage": "https://github.com/Seldaek/monolog", + "keywords": [ + "log", + "logging", + "psr-3" + ], + "funding": [ + { + "url": "https://github.com/Seldaek", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/monolog/monolog", + "type": "tidelift" + } + ], + "time": "2022-05-10T09:36:00+00:00" + }, + { + "name": "psr/http-client", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-client.git", + "reference": "2dfb5f6c5eff0e91e20e913f8c5452ed95b86621" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-client/zipball/2dfb5f6c5eff0e91e20e913f8c5452ed95b86621", + "reference": "2dfb5f6c5eff0e91e20e913f8c5452ed95b86621", + "shasum": "" + }, + "require": { + "php": "^7.0 || ^8.0", + "psr/http-message": "^1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Client\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP clients", + "homepage": "https://github.com/php-fig/http-client", + "keywords": [ + "http", + "http-client", + "psr", + "psr-18" + ], + "time": "2020-06-29T06:28:15+00:00" + }, + { + "name": "psr/http-factory", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-factory.git", + "reference": "12ac7fcd07e5b077433f5f2bee95b3a771bf61be" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-factory/zipball/12ac7fcd07e5b077433f5f2bee95b3a771bf61be", + "reference": "12ac7fcd07e5b077433f5f2bee95b3a771bf61be", + "shasum": "" + }, + "require": { + "php": ">=7.0.0", + "psr/http-message": "^1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interfaces for PSR-7 HTTP message factories", + "keywords": [ + "factory", + "http", + "message", + "psr", + "psr-17", + "psr-7", + "request", + "response" + ], + "time": "2019-04-30T12:38:16+00:00" + }, + { + "name": "psr/http-message", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-message.git", + "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363", + "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP messages", + "homepage": "https://github.com/php-fig/http-message", + "keywords": [ + "http", + "http-message", + "psr", + "psr-7", + "request", + "response" + ], + "time": "2016-08-06T14:39:51+00:00" + }, + { + "name": "psr/log", + "version": "1.1.4", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "d49695b909c3b7628b6289db5479a1c204601f11" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/d49695b909c3b7628b6289db5479a1c204601f11", + "reference": "d49695b909c3b7628b6289db5479a1c204601f11", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Log\\": "Psr/Log/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "time": "2021-05-03T11:20:27+00:00" + }, + { + "name": "ralouphie/getallheaders", + "version": "3.0.3", + "source": { + "type": "git", + "url": "https://github.com/ralouphie/getallheaders.git", + "reference": "120b605dfeb996808c31b6477290a714d356e822" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822", + "reference": "120b605dfeb996808c31b6477290a714d356e822", + "shasum": "" + }, + "require": { + "php": ">=5.6" + }, + "require-dev": { + "php-coveralls/php-coveralls": "^2.1", + "phpunit/phpunit": "^5 || ^6.5" + }, + "type": "library", + "autoload": { + "files": [ + "src/getallheaders.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ralph Khattar", + "email": "ralph.khattar@gmail.com" + } + ], + "description": "A polyfill for getallheaders.", + "time": "2019-03-08T08:55:37+00:00" + }, + { + "name": "shrikeh/teapot", + "version": "v2.3.1", + "source": { + "type": "git", + "url": "https://github.com/shrikeh/teapot.git", + "reference": "2fea5720963f22eedb920ee65b9d643bfa3e8daf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/shrikeh/teapot/zipball/2fea5720963f22eedb920ee65b9d643bfa3e8daf", + "reference": "2fea5720963f22eedb920ee65b9d643bfa3e8daf", + "shasum": "" + }, + "require": { + "php": ">=5.5", + "psr/http-message": "^1.0", + "teapot/status-code": "^1.0" + }, + "require-dev": { + "behat/behat": "^3.2", + "bossa/phpspec2-expect": "^2.0", + "escapestudios/symfony2-coding-standard": "^2.9", + "phpspec/phpspec": "~3.0.0", + "squizlabs/php_codesniffer": "^2.7" + }, + "type": "library", + "autoload": { + "psr-4": { + "Teapot\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Barney Hanlon", + "email": "barney@shrikeh.net" + }, + { + "name": "Andreas Möller", + "email": "am@localheinz.com" + } + ], + "description": "PHP HTTP Response Status library", + "homepage": "https://shrikeh.github.io/teapot/", + "keywords": [ + "http" + ], + "time": "2017-09-01T13:56:48+00:00" + }, + { + "name": "symfony/deprecation-contracts", + "version": "v2.5.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/deprecation-contracts.git", + "reference": "e8b495ea28c1d97b5e0c121748d6f9b53d075c66" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/e8b495ea28c1d97b5e0c121748d6f9b53d075c66", + "reference": "e8b495ea28c1d97b5e0c121748d6f9b53d075c66", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.5-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "files": [ + "function.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "A generic function and convention to trigger deprecation notices", + "homepage": "https://symfony.com", + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-01-02T09:53:40+00:00" + }, + { + "name": "teapot/status-code", + "version": "v1.1.2", + "source": { + "type": "git", + "url": "https://github.com/teapot-php/status-code.git", + "reference": "7aaba4364645ebb9d3a36267c9b3a32206d3042b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/teapot-php/status-code/zipball/7aaba4364645ebb9d3a36267c9b3a32206d3042b", + "reference": "7aaba4364645ebb9d3a36267c9b3a32206d3042b", + "shasum": "" + }, + "require": { + "php": "^5.4 || ^7.0 || ^8.0" + }, + "require-dev": { + "squizlabs/php_codesniffer": "^3.5.8" + }, + "type": "library", + "autoload": { + "psr-4": { + "Teapot\\StatusCode\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Barney Hanlon", + "email": "barney@shrikeh.net" + } + ], + "description": "PHP HTTP Response Status code library", + "homepage": "http://shrikeh.github.com/teapot", + "keywords": [ + "http" + ], + "time": "2020-11-03T17:14:32+00:00" + } + ], + "packages-dev": [], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": [], + "platform-dev": [], + "plugin-api-version": "1.1.0" +} diff --git a/backend/config/config.template.php b/backend/config/config.template.php index 780a61d..5d52694 100644 --- a/backend/config/config.template.php +++ b/backend/config/config.template.php @@ -1,10 +1,12 @@ false, - + 'site' => [ 'base_url' => 'http://localhost/api', - 'salt' => 'any_random_string' + 'domain' => 'localhost', + 'salt' => 'any_random_string', + 'csrf_time' => '1800' // In seconds ], 'db' => [ @@ -12,6 +14,14 @@ 'user' => 'root', 'pass' => '', 'name' => 'harcdzielnia' + ], + + 'cloudinary' => [ + 'cloud_name' => '', // Cloudinary cloud name + 'api_key' => '', // Cloudinary API key + 'api_secret' => '', // Cloudinary API secret + 'folder' => 'harcdzielnia/' // Cloudinary selected folder (end with a slash) + + // More info at https://cloudinary.com/documentation/php_integration#setting_parameters_globally ] ]; -?> \ No newline at end of file diff --git a/backend/config/functions.php b/backend/config/functions.php index dfe7bf4..54ba1ac 100644 --- a/backend/config/functions.php +++ b/backend/config/functions.php @@ -1,7 +1,7 @@ set_charset('utf8'); @@ -26,4 +30,63 @@ function apiReturn($status_code, $response){ function sanitizeStr($str){ return htmlentities($str, ENT_QUOTES, "UTF-8"); } -?> \ No newline at end of file + +function randomStr($length){ + return bin2hex(random_bytes($length)); +} + +function getCsrf(){ + if (isset($_SESSION['csrf'])) { + $token_age = $timestamp - $_SESSION['csrf_time']; + if ($token_age <= $config['site']['csrf_time']){ + return $_SESSION['csrf']; + } else { + $_SESSION['csrf'] = sha1(randomStr().$user_agent); + $_SESSION['csrf_time'] = $timestamp; + return $_SESSION['csrf']; + } + } else { + $_SESSION['csrf'] = sha1(randomStr().$user_agent); + $_SESSION['csrf_time'] = $timestamp; + return $_SESSION['csrf']; + } + setcookie("csrf", $_SESSION['csrf'], $config['site']['csrf_time'], '/', $config['site']['domain'], true, false, 'Lax'); +} + +function verifyCsrf($token){ + if (isset($_SESSION['csrf'])) { + $token_age = $timestamp - $_SESSION['csrf_time']; + if ($token_age <= $config['site']['csrf_time']){ + if ($token == $_SESSION['csrf']) { + unset($_SESSION['csrf']); + unset($_SESSION['csrf_time']); + return true; + } else { + unset($_SESSION['csrf']); + unset($_SESSION['csrf_time']); + return false; + } + } else { + unset($_SESSION['csrf']); + unset($_SESSION['csrf_time']); + return false; + } + } else { + return false; + } +} + +function userPerms($code){ + switch ($code){ + case 0: + $perms = "Użytkownik"; + break; + case 1: + $perms = "Redaktor serwisu"; + break; + case 2: + $perms = "Administrator"; + break; + return $perms; + } +} \ No newline at end of file diff --git a/backend/db.sql b/backend/db.sql index 504c6ee..6b7d81c 100644 --- a/backend/db.sql +++ b/backend/db.sql @@ -4,8 +4,10 @@ CREATE TABLE `items` ( `name` text NOT NULL, `description` text NOT NULL, `image_url` text NOT NULL, + `image_id` text NOT NULL, `order_type` int(1) NOT NULL, `contact_info` text NOT NULL, + `email` text NOT NULL, `timestamp` int(11) NOT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; @@ -17,15 +19,27 @@ CREATE TABLE `users` ( `permissions` int(1) NOT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; +CREATE TABLE `tokens` ( + `id` int(11) NOT NULL, + `token_hash` text NOT NULL, + `type` int(1) NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + ALTER TABLE `items` ADD PRIMARY KEY (`id`); ALTER TABLE `users` ADD PRIMARY KEY (`id`); +ALTER TABLE `tokens` + ADD PRIMARY KEY (`id`); + ALTER TABLE `items` MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; ALTER TABLE `users` MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; + +ALTER TABLE `tokens` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; COMMIT; diff --git a/backend/includes/authentication.php b/backend/includes/authentication.php index 95fe5d7..028c647 100644 --- a/backend/includes/authentication.php +++ b/backend/includes/authentication.php @@ -1,3 +1,37 @@ - \ No newline at end of file +if(isset($permission) && !isset($_SESSION['user_id'])){ + $status_code = 401; + $response = [ + 'status' => 'Error', + 'message' => 'Unauthorized' + ]; + + apiReturn($status_code, $response); + die(); +} else { + +$user_id = $_SESSION['user_id']; + +$sql = "SELECT name,email,permissions FROM user WHERE id=$user_id"; + $result = $db->query($sql); + + $user = array(); + $row = $result->fetch_assoc(); + $user['name'] = $row['name']; + $user['email'] = $row['email']; + $user['permissions'] = userPerms($row['permissions']); + $user_perms = $row['permissions']; + +if ($permission > $user_perms) { + $status_code = 403; + $response = [ + 'status' => 'Error', + 'message' => 'Forbidden' + ]; + + apiReturn($status_code, $response); + die(); +} +} \ No newline at end of file diff --git a/backend/includes/cloudinary.php b/backend/includes/cloudinary.php new file mode 100644 index 0000000..feb0b69 --- /dev/null +++ b/backend/includes/cloudinary.php @@ -0,0 +1,16 @@ + [ + 'cloud_name' => $config['cloudinary']['cloud_name'], + 'api_key' => $config['cloudinary']['api_key'], + 'api_secret' => $config['cloudinary']['api_secret'], + ], + 'url' => [ + 'secure' => true + ] +]); diff --git a/backend/includes/header.php b/backend/includes/header.php index c2b0985..f76f184 100644 --- a/backend/includes/header.php +++ b/backend/includes/header.php @@ -1,8 +1,8 @@ 'Error', @@ -13,9 +13,12 @@ die(); } -require('authentication.php'); +require 'authentication.php'; -if(!empty($_GET['id'])){ +if (!empty($_GET['id'])) { $id = sanitizeStr($_GET['id']); } -?> \ No newline at end of file + +if (!empty($_GET['token'])) { + $id = sanitizeStr($_GET['token']); +} diff --git a/backend/routes/hello.php b/backend/routes/hello.php deleted file mode 100644 index 7c67348..0000000 --- a/backend/routes/hello.php +++ /dev/null @@ -1,11 +0,0 @@ - 'Hello world' -]; - -apiReturn($status_code, $response); -?> \ No newline at end of file diff --git a/backend/routes/items.php b/backend/routes/items.php deleted file mode 100644 index 9eafc58..0000000 --- a/backend/routes/items.php +++ /dev/null @@ -1,24 +0,0 @@ -query($sql); - if($result->num_rows == 0){ - $items = 0; - } else { - $items = array(); - while($row = $result->fetch_assoc()){ - $items[$row['id']]['name'] = $row['name']; - $items[$row['id']]['image_url'] = $row['image_url']; - } - } - -$status_code = 200; -$response = [ - 'items' => $items -]; - -apiReturn($status_code, $response); -?> \ No newline at end of file diff --git a/backend/routes/public/item.php b/backend/routes/public/item.php new file mode 100644 index 0000000..65e4cc2 --- /dev/null +++ b/backend/routes/public/item.php @@ -0,0 +1,28 @@ +prepare($sql); +$stmt->bind_param("i", $id); +$stmt->execute(); + +$result = $stmt->get_result(); +if ($result->num_rows == 0) { + $items = 0; +} else { + $item = array(); + $row = $result->fetch_assoc(); + $item['name'] = $row['name']; + $item['description'] = $row['description']; + $item['image_url'] = $row['image_url']; + $item['order_type'] = $row['order_type']; + $item['contact_info'] = $row['contact_info']; +} + +$status_code = 200; +$response = [ + 'item' => $item +]; + +apiReturn($status_code, $response); diff --git a/backend/routes/public/items.php b/backend/routes/public/items.php new file mode 100644 index 0000000..e6622bd --- /dev/null +++ b/backend/routes/public/items.php @@ -0,0 +1,23 @@ +query($sql); +if ($result->num_rows == 0) { + $items = 0; +} else { + $items = array(); + while ($row = $result->fetch_assoc()) { + $items[$row['id']]['name'] = $row['name']; + $items[$row['id']]['image_url'] = $row['image_url']; + } +} + +$status_code = 200; +$response = [ + 'items' => $items +]; + +apiReturn($status_code, $response);