diff --git a/README.md b/README.md index fb7388a54..e7812e08b 100644 --- a/README.md +++ b/README.md @@ -1,62 +1,31 @@ -# Laravel Live Coding Test +## Installation -## Follow this steps +Clone the project +```bash +git clone https://github.com/csfwn/laravel-coding-test-level-1.git +``` -#### Application Setup (DO THIS FIRST) +Install required packages +```bash +composer install +``` -- **Fork this repository** into your **GitHub** account (You can create a **GitHub** account if you don't have one) -- Clone the repository from **your repository** +Setup environment configuration and update it accordingly (db, app key etc) +```bash +cp .env.example .env +``` -#### First Test - CRUD REST API +Migrate DB and seeder +```bash +php artisan migrate:fresh --seed +``` +> Set the db config before run miration -- Make sure that you are in `main` branch -- Create a new branch and name it `1-crud-api` -- Create a model with name `Event` -- `Event` will have these properties - - **id** -> PK, UNIQUE, value must be a UUID - - **name** -> String - - **slug** -> UNIQUE, String - - **createdAt** -> NOT NULL, DateTime - - **updatedAt** -> NOT NULL, DateTime -- Create these APIs - - GET /api/v1/events -> Return all events from the database - - GET /api/v1/events/active-events -> Return all events that are active = current datetime is within startAt and endAt - - GET /api/v1/events/{id} -> Get one event - - POST /api/v1/events -> Create an event - - PUT /api/v1/events/{id} -> Create event if not exist, else update the event in idempotent way - - PATCH /api/v1/events/{id} -> Partially update event - - DELETE /api/v1/events/{id} -> Soft delete an event -- Seed the database with dummy events (min. 5 events) -- Merge `1-crud-api` with `main`, use PR +Install Vue & Start +```bash +npm install +npm run dev +``` +> Please use laravel directory to composer install, npm install, npm run dev -#### Second Test - UI -- Make sure that you are in `main` branch -- Create a new branch and name it `2-ui` -- Create these views - - /events -> Show all events in the table (search and pagination has bonus point). Last column should display 2 buttons on each row to update and delete the event - - /events/{id} -> Show individual event - - /events/create -> Create an event - - /events/{id}/edit -> Edit an event -- Merge `2-ui` with `main`, use PR - -#### Third Test - Advance Topic - -- Make sure that you are in `main` branch -- Create a new branch and name it `3-advance-topic` -- Implement these features - - Server side data caching with redis - - Send an email everytime an event is created (you can use mailtrap or other smtp provider that's easy to setup) - - Authentication -> only authenticated users can create, update and delete events - - Calling of an external API(s) and display the data in the UI - -## Bonus points - -- If you follow a clean code principle -- If you follow a good git practice -- If you deploy the application on the internet - -## Finally - -- Push all the codes into the your remote repository -- Make sure the repository is public diff --git a/laravel/.editorconfig b/laravel/.editorconfig new file mode 100644 index 000000000..1671c9b9d --- /dev/null +++ b/laravel/.editorconfig @@ -0,0 +1,18 @@ +root = true + +[*] +charset = utf-8 +end_of_line = lf +insert_final_newline = true +indent_style = space +indent_size = 4 +trim_trailing_whitespace = true + +[*.md] +trim_trailing_whitespace = false + +[*.{yml,yaml}] +indent_size = 2 + +[docker-compose.yml] +indent_size = 4 diff --git a/laravel/.env.example b/laravel/.env.example new file mode 100644 index 000000000..b7becbac4 --- /dev/null +++ b/laravel/.env.example @@ -0,0 +1,52 @@ +APP_NAME=Laravel +APP_ENV=local +APP_KEY= +APP_DEBUG=true +APP_URL=http://localhost + +LOG_CHANNEL=stack +LOG_DEPRECATIONS_CHANNEL=null +LOG_LEVEL=debug + +DB_CONNECTION=mysql +DB_HOST=127.0.0.1 +DB_PORT=3306 +DB_DATABASE=laravel +DB_USERNAME=root +DB_PASSWORD= + +BROADCAST_DRIVER=log +CACHE_DRIVER=file +FILESYSTEM_DRIVER=local +QUEUE_CONNECTION=sync +SESSION_DRIVER=file +SESSION_LIFETIME=120 + +MEMCACHED_HOST=127.0.0.1 + +REDIS_HOST=127.0.0.1 +REDIS_PASSWORD=null +REDIS_PORT=6379 + +MAIL_MAILER=smtp +MAIL_HOST=mailhog +MAIL_PORT=1025 +MAIL_USERNAME=null +MAIL_PASSWORD=null +MAIL_ENCRYPTION=null +MAIL_FROM_ADDRESS=null +MAIL_FROM_NAME="${APP_NAME}" + +AWS_ACCESS_KEY_ID= +AWS_SECRET_ACCESS_KEY= +AWS_DEFAULT_REGION=us-east-1 +AWS_BUCKET= +AWS_USE_PATH_STYLE_ENDPOINT=false + +PUSHER_APP_ID= +PUSHER_APP_KEY= +PUSHER_APP_SECRET= +PUSHER_APP_CLUSTER=mt1 + +MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}" +MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}" diff --git a/laravel/.gitattributes b/laravel/.gitattributes new file mode 100644 index 000000000..510d9961f --- /dev/null +++ b/laravel/.gitattributes @@ -0,0 +1,10 @@ +* text=auto + +*.blade.php diff=html +*.css diff=css +*.html diff=html +*.md diff=markdown +*.php diff=php + +/.github export-ignore +CHANGELOG.md export-ignore diff --git a/laravel/.gitignore b/laravel/.gitignore new file mode 100644 index 000000000..eb003b01a --- /dev/null +++ b/laravel/.gitignore @@ -0,0 +1,15 @@ +/node_modules +/public/hot +/public/storage +/storage/*.key +/vendor +.env +.env.backup +.phpunit.result.cache +docker-compose.override.yml +Homestead.json +Homestead.yaml +npm-debug.log +yarn-error.log +/.idea +/.vscode diff --git a/laravel/.styleci.yml b/laravel/.styleci.yml new file mode 100644 index 000000000..877ea701d --- /dev/null +++ b/laravel/.styleci.yml @@ -0,0 +1,14 @@ +php: + preset: laravel + version: 8 + disabled: + - no_unused_imports + finder: + not-name: + - index.php + - server.php +js: + finder: + not-name: + - webpack.mix.js +css: true diff --git a/laravel/README.md b/laravel/README.md new file mode 100644 index 000000000..1b6397ce3 --- /dev/null +++ b/laravel/README.md @@ -0,0 +1,64 @@ +
+ + + +## About Laravel + +Laravel is a web application framework with expressive, elegant syntax. We believe development must be an enjoyable and creative experience to be truly fulfilling. Laravel takes the pain out of development by easing common tasks used in many web projects, such as: + +- [Simple, fast routing engine](https://laravel.com/docs/routing). +- [Powerful dependency injection container](https://laravel.com/docs/container). +- Multiple back-ends for [session](https://laravel.com/docs/session) and [cache](https://laravel.com/docs/cache) storage. +- Expressive, intuitive [database ORM](https://laravel.com/docs/eloquent). +- Database agnostic [schema migrations](https://laravel.com/docs/migrations). +- [Robust background job processing](https://laravel.com/docs/queues). +- [Real-time event broadcasting](https://laravel.com/docs/broadcasting). + +Laravel is accessible, powerful, and provides tools required for large, robust applications. + +## Learning Laravel + +Laravel has the most extensive and thorough [documentation](https://laravel.com/docs) and video tutorial library of all modern web application frameworks, making it a breeze to get started with the framework. + +If you don't feel like reading, [Laracasts](https://laracasts.com) can help. Laracasts contains over 1500 video tutorials on a range of topics including Laravel, modern PHP, unit testing, and JavaScript. Boost your skills by digging into our comprehensive video library. + +## Laravel Sponsors + +We would like to extend our thanks to the following sponsors for funding Laravel development. If you are interested in becoming a sponsor, please visit the Laravel [Patreon page](https://patreon.com/taylorotwell). + +### Premium Partners + +- **[Vehikl](https://vehikl.com/)** +- **[Tighten Co.](https://tighten.co)** +- **[Kirschbaum Development Group](https://kirschbaumdevelopment.com)** +- **[64 Robots](https://64robots.com)** +- **[Cubet Techno Labs](https://cubettech.com)** +- **[Cyber-Duck](https://cyber-duck.co.uk)** +- **[Many](https://www.many.co.uk)** +- **[Webdock, Fast VPS Hosting](https://www.webdock.io/en)** +- **[DevSquad](https://devsquad.com)** +- **[Curotec](https://www.curotec.com/services/technologies/laravel/)** +- **[OP.GG](https://op.gg)** +- **[WebReinvent](https://webreinvent.com/?utm_source=laravel&utm_medium=github&utm_campaign=patreon-sponsors)** +- **[Lendio](https://lendio.com)** + +## Contributing + +Thank you for considering contributing to the Laravel framework! The contribution guide can be found in the [Laravel documentation](https://laravel.com/docs/contributions). + +## Code of Conduct + +In order to ensure that the Laravel community is welcoming to all, please review and abide by the [Code of Conduct](https://laravel.com/docs/contributions#code-of-conduct). + +## Security Vulnerabilities + +If you discover a security vulnerability within Laravel, please send an e-mail to Taylor Otwell via [taylor@laravel.com](mailto:taylor@laravel.com). All security vulnerabilities will be promptly addressed. + +## License + +The Laravel framework is open-sourced software licensed under the [MIT license](https://opensource.org/licenses/MIT). diff --git a/laravel/app/Actions/Auth/CreateUser.php b/laravel/app/Actions/Auth/CreateUser.php new file mode 100644 index 000000000..b40d0d12f --- /dev/null +++ b/laravel/app/Actions/Auth/CreateUser.php @@ -0,0 +1,33 @@ + 'required|string', + 'email' => 'required|email|unique:users,email', + 'password' => 'required|string|confirmed' + ]; + } + + public function handle() + { + $user = User::create( + [ + 'name' => $this->name, + 'email' => $this->email, + 'password' => bcrypt($this->password) + ] + ); + + $token = $user->createToken('myToken')->plainTextToken; + + return ['user' => $user, 'token' => $token]; + } +} diff --git a/laravel/app/Actions/Auth/LoginUser.php b/laravel/app/Actions/Auth/LoginUser.php new file mode 100644 index 000000000..d893cf4f7 --- /dev/null +++ b/laravel/app/Actions/Auth/LoginUser.php @@ -0,0 +1,32 @@ + 'required|email', + 'password' => 'required|string' + ]; + } + + public function handle() + { + $user = User::whereEmail($this->email)->first(); + + if (!$user || !Hash::check($this->password, $user->password)) { + throw new GeneralHttpException('Wrong Email or Password'); + } + + $token = $user->createToken('myToken')->plainTextToken; + + return ['user' => $user, 'token' => $token]; + } +} diff --git a/laravel/app/Actions/Events/CreateEvent.php b/laravel/app/Actions/Events/CreateEvent.php new file mode 100644 index 000000000..24b43fc89 --- /dev/null +++ b/laravel/app/Actions/Events/CreateEvent.php @@ -0,0 +1,27 @@ + 'required', + 'slug' => 'required', + ]; + } + + public function handle() + { + return Event::create( + [ + 'name' => $this->name, + 'slug' => $this->slug, + ] + ); + } +} diff --git a/laravel/app/Actions/Events/UpdateEvent.php b/laravel/app/Actions/Events/UpdateEvent.php new file mode 100644 index 000000000..353421366 --- /dev/null +++ b/laravel/app/Actions/Events/UpdateEvent.php @@ -0,0 +1,31 @@ + 'required', + 'slug' => 'required', + ]; + } + + public function handle(Request $request) + { + return Event::updateOrCreate( + [ + 'id' => $request->id + ], + [ + 'name' => $this->name, + 'slug' => $this->slug + ] + ); + } +} diff --git a/laravel/app/Console/Kernel.php b/laravel/app/Console/Kernel.php new file mode 100644 index 000000000..d8bc1d29f --- /dev/null +++ b/laravel/app/Console/Kernel.php @@ -0,0 +1,32 @@ +command('inspire')->hourly(); + } + + /** + * Register the commands for the application. + * + * @return void + */ + protected function commands() + { + $this->load(__DIR__.'/Commands'); + + require base_path('routes/console.php'); + } +} diff --git a/laravel/app/Exceptions/GeneralHttpException.php b/laravel/app/Exceptions/GeneralHttpException.php new file mode 100644 index 000000000..bfce3ff9e --- /dev/null +++ b/laravel/app/Exceptions/GeneralHttpException.php @@ -0,0 +1,19 @@ +> + */ + protected $dontReport = [ + // + ]; + + /** + * A list of the inputs that are never flashed for validation exceptions. + * + * @var array