├── .circleci
└── config.yml
├── .codecov.yml
├── .documents
└── whiteboard
│ ├── .gitignore
│ ├── LICENSE
│ ├── README.md
│ ├── _config.yml
│ ├── lib
│ └── whiteboard.js
│ ├── package.json
│ ├── source
│ ├── images
│ │ ├── logo.png
│ │ └── navbar.png
│ ├── includes
│ │ ├── _authenticate.md
│ │ └── _errors.md
│ └── index.md
│ ├── themes
│ └── whiteboard
│ │ ├── .gitignore
│ │ ├── _config.yml
│ │ ├── layout
│ │ └── index.ejs
│ │ ├── scripts
│ │ ├── highlight.js
│ │ └── read.js
│ │ └── source
│ │ ├── css
│ │ ├── _icon_font.styl
│ │ ├── _monokai.css
│ │ ├── _normalize.css
│ │ ├── _variables.styl
│ │ ├── fonts
│ │ │ ├── FontAwesome.otf
│ │ │ ├── fontawesome-webfont.eot
│ │ │ ├── fontawesome-webfont.svg
│ │ │ ├── fontawesome-webfont.ttf
│ │ │ └── fontawesome-webfont.woff
│ │ └── style.styl
│ │ └── js
│ │ ├── lib
│ │ ├── energize.js
│ │ ├── imagesloaded.min.js
│ │ ├── jquery.highlight.js
│ │ ├── jquery.tocify.js
│ │ ├── jquery_ui.js
│ │ └── lunr.js
│ │ └── script.js
│ └── yarn.lock
├── .editorconfig
├── .env.dev.example
├── .env.example
├── .envs
└── dev
│ ├── cert
│ ├── Dockerfile
│ ├── command.sh
│ ├── create-certs.sh
│ ├── create-htpasswd.sh
│ ├── create-rootCA.sh
│ ├── entrypoint.sh
│ ├── files
│ │ └── .gitignore
│ ├── rootCA.csr.cnf
│ └── v3.ext
│ ├── common
│ └── wait-for-it.sh
│ ├── memcached
│ └── Dockerfile
│ ├── mysql
│ ├── .gitignore
│ ├── Dockerfile
│ └── entrypoint.sh
│ ├── nginx
│ ├── .gitignore
│ ├── Dockerfile
│ ├── command.sh
│ ├── conf.d
│ │ ├── default.conf
│ │ ├── documents.conf
│ │ ├── ip-whitelist.conf
│ │ └── phpmyadmin.conf
│ ├── logs
│ │ └── .gitkeep
│ └── nginx.conf
│ ├── node
│ ├── Dockerfile
│ └── command.sh
│ ├── php
│ ├── Dockerfile
│ ├── command.sh
│ ├── crontab
│ │ ├── cron.daily.logrotate
│ │ ├── cron.minutely.schedule
│ │ └── crontab
│ ├── entrypoint.sh
│ ├── passport.sh
│ ├── php-fpm.conf
│ ├── php-worker
│ ├── php-worker.conf
│ ├── php.ini
│ └── www.conf
│ ├── phpcs
│ └── SunOS
│ │ └── ruleset.xml
│ └── phpmyadmin
│ ├── command.sh
│ ├── phpMyAdmin-4.8.5.tar.gz
│ └── src
│ └── .gitignore
├── .eslintignore
├── .eslintrc.js
├── .gitattributes
├── .github
└── PULL_REQUEST_TEMPLATE.md
├── .gitignore
├── .stylelintignore
├── .stylelintrc.js
├── app
├── Console
│ ├── Commands
│ │ └── GitGetCommit.php
│ └── Kernel.php
├── Events
│ └── ExceptionThrown.php
├── Exceptions
│ ├── Api
│ │ ├── ActionException.php
│ │ ├── ApiException.php
│ │ ├── NotFoundException.php
│ │ ├── NotOwnerException.php
│ │ └── UnknownException.php
│ ├── Handler.php
│ └── Permission
│ │ ├── PermissionDoesNotExist.php
│ │ ├── RoleDoesNotExist.php
│ │ └── UnauthorizedException.php
├── Http
│ ├── Controllers
│ │ ├── Api
│ │ │ ├── ApiController.php
│ │ │ ├── Auth
│ │ │ │ ├── ForgotPasswordController.php
│ │ │ │ └── LoginController.php
│ │ │ └── UserController.php
│ │ ├── Controller.php
│ │ └── Web
│ │ │ ├── Auth
│ │ │ ├── ForgotPasswordController.php
│ │ │ ├── LoginController.php
│ │ │ ├── RegisterController.php
│ │ │ ├── ResetPasswordController.php
│ │ │ └── VerificationController.php
│ │ │ ├── ExportController.php
│ │ │ ├── HomeController.php
│ │ │ ├── ImportController.php
│ │ │ ├── UserController.php
│ │ │ └── WebController.php
│ ├── Kernel.php
│ ├── Middleware
│ │ ├── Authenticate.php
│ │ ├── CheckForMaintenanceMode.php
│ │ ├── EncryptCookies.php
│ │ ├── Permission
│ │ │ ├── PermissionMiddleware.php
│ │ │ └── RoleMiddleware.php
│ │ ├── RedirectIfAuthenticated.php
│ │ ├── TrimStrings.php
│ │ ├── TrustProxies.php
│ │ └── VerifyCsrfToken.php
│ ├── Requests
│ │ ├── Auth
│ │ │ ├── ForgotPasswordRequest.php
│ │ │ ├── LoginRequest.php
│ │ │ ├── RegisterRequest.php
│ │ │ └── ResetPasswordRequest.php
│ │ ├── ExportFormRequest.php
│ │ └── ImportFileCsvRequest.php
│ └── Resources
│ │ ├── ApiCollection.php
│ │ ├── ApiResource.php
│ │ ├── AuthResource.php
│ │ ├── ExportResource.php
│ │ └── UserResource.php
├── Libraries
│ ├── ChatApp
│ │ ├── ChatAppException.php
│ │ ├── ChatAppHandler.php
│ │ ├── ChatAppManager.php
│ │ ├── Handlers
│ │ │ ├── Chatwork.php
│ │ │ └── Slack.php
│ │ └── Messages
│ │ │ ├── Chatwork.php
│ │ │ └── Slack.php
│ ├── PermissionRegister.php
│ └── helpers.php
├── Listeners
│ └── ExceptionThrownListener.php
├── Mail
│ └── MailForgotPassword.php
├── Models
│ ├── BaseModel.php
│ ├── Import.php
│ ├── PasswordResetToken.php
│ ├── Permission.php
│ ├── Role.php
│ └── User.php
├── Policies
│ └── AbstractPolicy.php
├── Providers
│ ├── AppServiceProvider.php
│ ├── AuthServiceProvider.php
│ ├── BroadcastServiceProvider.php
│ ├── ChatAppProvider.php
│ ├── EventServiceProvider.php
│ ├── PermissionServiceProvider.php
│ ├── RepositoryServiceProvider.php
│ └── RouteServiceProvider.php
├── Repositories
│ ├── AppRepository.php
│ ├── AppRepositoryInterface.php
│ ├── ExportRepository.php
│ ├── ExportRepositoryInterface.php
│ ├── ImportRepository.php
│ ├── ImportRepositoryInterface.php
│ ├── PasswordResetTokenRepository.php
│ ├── PasswordResetTokenRepositoryInterface.php
│ ├── PermissionRepository.php
│ ├── PermissionRepositoryInterface.php
│ ├── RoleRepository.php
│ ├── RoleRepositoryInterface.php
│ ├── UserRepository.php
│ └── UserRepositoryInterface.php
├── Rules
│ ├── CheckEmail.php
│ ├── CheckExtension.php
│ ├── CheckImportFile.php
│ └── CheckValidPasswordResetToken.php
├── Services
│ ├── AppService.php
│ ├── AuthService.php
│ ├── ExportService.php
│ ├── ImportService.php
│ └── UserService.php
└── Traits
│ ├── RoleHasPermissions.php
│ └── UserHasRolesAndPermissions.php
├── artisan
├── bootstrap
├── app.php
└── cache
│ └── .gitignore
├── composer.json
├── composer.lock
├── config
├── api.php
├── app.php
├── auth.php
├── broadcasting.php
├── cache.php
├── common.php
├── database.php
├── filesystems.php
├── hashing.php
├── laroute.php
├── logging.php
├── mail.php
├── permission.php
├── queue.php
├── services.php
├── session.php
├── view.php
└── web.php
├── database
├── .gitignore
├── factories
│ ├── ImportFactory.php
│ ├── PermissionFactory.php
│ ├── RoleFactory.php
│ └── UserFactory.php
├── migrations
│ ├── 2014_10_12_000000_create_users_table.php
│ ├── 2014_10_12_100000_create_password_resets_table.php
│ ├── 2019_05_27_071248_create_roles_and_permissions_table.php
│ └── 2019_08_19_102724_create_imports_table.php
└── seeds
│ ├── DatabaseSeeder.php
│ ├── RolePermissionSeeder.php
│ └── UserTableSeeder.php
├── docker-compose.dev.yml
├── docker.sh
├── mergeManifest.js
├── package.json
├── phpunit.xml
├── public
├── .htaccess
├── css
│ └── .gitignore
├── export.csv
├── favicon.ico
├── index.php
├── js
│ └── .gitignore
├── robots.txt
└── web.config
├── readme.md
├── resources
├── js
│ ├── App.vue
│ ├── app.js
│ ├── components
│ │ ├── Login
│ │ │ ├── Authentication.vue
│ │ │ └── Registeration.vue
│ │ └── Navbar
│ │ │ └── Navbar.vue
│ ├── constants
│ │ └── index.js
│ ├── langs
│ │ ├── en.js
│ │ └── vi.js
│ ├── mixins
│ │ └── RedirectIfAuthenticated.js
│ ├── pages
│ │ ├── Auth
│ │ │ ├── LoginPage.vue
│ │ │ └── RegisterPage.vue
│ │ ├── DashboardPage.vue
│ │ ├── Export.vue
│ │ └── Layout
│ │ │ └── AppLayout.vue
│ ├── router
│ │ ├── index.js
│ │ └── middlewares
│ │ │ └── auth.js
│ ├── store
│ │ ├── auth
│ │ │ ├── index.js
│ │ │ └── mutation-types.js
│ │ └── index.js
│ └── utils
│ │ ├── api.js
│ │ ├── env.js
│ │ ├── i18n
│ │ ├── formatter.js
│ │ └── index.js
│ │ ├── index.js
│ │ ├── route.js
│ │ └── swal.js
├── lang
│ └── en
│ │ ├── auth.php
│ │ ├── common.php
│ │ ├── exception.php
│ │ ├── export.php
│ │ ├── http_message.php
│ │ ├── import.php
│ │ ├── pagination.php
│ │ ├── passwords.php
│ │ └── validation.php
├── sass
│ ├── _mixins.scss
│ ├── _variables.scss
│ └── app.scss
└── views
│ ├── auth
│ ├── login.blade.php
│ ├── passwords
│ │ ├── email.blade.php
│ │ └── reset.blade.php
│ ├── register.blade.php
│ └── verify.blade.php
│ ├── client.blade.php
│ ├── emails
│ └── mail_forgot_password.blade.php
│ ├── home.blade.php
│ ├── imports
│ └── index.blade.php
│ ├── layouts
│ └── app.blade.php
│ └── notification_template
│ ├── chatwork.blade.php
│ └── slack.blade.php
├── routes
├── api.php
├── channels.php
├── console.php
└── web.php
├── server.php
├── storage
├── app
│ ├── .gitignore
│ └── public
│ │ └── .gitignore
├── framework
│ ├── .gitignore
│ ├── cache
│ │ ├── .gitignore
│ │ └── data
│ │ │ └── .gitignore
│ ├── sessions
│ │ └── .gitignore
│ ├── testing
│ │ └── .gitignore
│ └── views
│ │ └── .gitignore
└── logs
│ └── .gitignore
├── tests
├── CreatesApplication.php
├── Feature
│ └── Http
│ │ └── Controller
│ │ └── Web
│ │ └── Auth
│ │ ├── ForgetPasswordControllerTest.php
│ │ ├── LoginControllerTest.php
│ │ ├── RegisterControllerTest.php
│ │ └── ResetPasswordControllerTest.php
├── ModelTestCase.php
├── TestCase.php
├── Unit
│ ├── ExampleTest.php
│ ├── Http
│ │ ├── Controller
│ │ │ └── Web
│ │ │ │ ├── Auth
│ │ │ │ ├── LoginControllerTest.php
│ │ │ │ └── RegisterControllerTest.php
│ │ │ │ ├── ExportControllerTest.php
│ │ │ │ └── ImportControllerTest.php
│ │ ├── Middleware
│ │ │ ├── PermissionMiddlewareTest.php
│ │ │ └── RoleMiddlewareTest.php
│ │ └── Requests
│ │ │ ├── ExportFormRequestTest.php
│ │ │ └── ImportFileCsvRequestTest.php
│ ├── Libraries
│ │ └── PermissionRegisterTest.php
│ ├── Models
│ │ ├── PermissionTest.php
│ │ ├── RoleTest.php
│ │ └── UserTest.php
│ ├── Repositories
│ │ ├── ExportRepositoryTest.php
│ │ └── ImportRepositoryTest.php
│ ├── Rules
│ │ └── CheckImportFileTest.php
│ ├── Services
│ │ ├── ExportServiceTest.php
│ │ └── ImportServiceTest.php
│ └── Traits
│ │ ├── RoleHasPermissionsTest.php
│ │ └── UserHasRolesAndPermissionsTest.php
└── files
│ ├── data_check_header_rule.csv
│ ├── data_check_row_rule.csv
│ └── data_check_rule.csv
├── webpack.css.mix.js
├── webpack.js.mix.js
└── yarn.lock
/.codecov.yml:
--------------------------------------------------------------------------------
1 | codecov:
2 | notify:
3 | require_ci_to_pass: yes
4 |
5 | coverage:
6 | precision: 2
7 | round: down
8 | range: "70...100"
9 |
10 | status:
11 | project: yes
12 | patch: yes
13 | changes: no
14 |
15 | parsers:
16 | gcov:
17 | branch_detection:
18 | conditional: yes
19 | loop: yes
20 | method: no
21 | macro: no
22 |
23 | comment:
24 | layout: "header, diff"
25 | behavior: default
26 | require_changes: no
27 |
--------------------------------------------------------------------------------
/.documents/whiteboard/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | Thumbs.db
3 | db.json
4 | *.log
5 | node_modules/
6 | public/
7 | .deploy*/
--------------------------------------------------------------------------------
/.documents/whiteboard/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright 2016 Marcel Pociot
2 | Copyright 2008-2013 Concur Technologies, Inc.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License"); you may
5 | not use this file except in compliance with the License. You may obtain
6 | a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 | WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 | License for the specific language governing permissions and limitations
14 | under the License.
15 |
--------------------------------------------------------------------------------
/.documents/whiteboard/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | # Whiteboard
4 | #### Simply write beautiful API documentation.
5 |
--------------------------------------------------------------------------------
/.documents/whiteboard/_config.yml:
--------------------------------------------------------------------------------
1 | # Whiteboard Configuration
2 | ## Docs: https://hexo.io/docs/configuration.html
3 |
4 | # Site
5 | title: API Documentation
6 | subtitle:
7 | description:
8 | author: John Doe
9 | language:
10 | timezone:
11 |
12 | # URL (Used when deploying)
13 | ## If your site is put in a subdirectory, set url as 'http://yoursite.com/child' and root as '/child/'
14 | url: http://yoursite.com
15 | root: /
16 |
17 | # Directory
18 | source_dir: source
19 | public_dir: public
20 | i18n_dir: :lang
21 | skip_render:
22 |
23 | # Writing
24 | relative_link: true
25 | future: true
26 | highlight:
27 | enable: true
28 | line_number: false
29 | auto_detect: false
30 | tab_replace:
31 |
32 | # Extensions
33 | ## Plugins: https://hexo.io/plugins/
34 | ## Themes: https://hexo.io/themes/
35 | theme: whiteboard
36 |
37 | # Deployment
38 | ## Docs: https://hexo.io/docs/deployment.html
39 | deploy:
40 | type:
41 |
42 |
--------------------------------------------------------------------------------
/.documents/whiteboard/lib/whiteboard.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var Hexo = require('hexo');
4 | var hexo = new Hexo();
5 | var Promise = require("bluebird");
6 |
7 | module.exports = {
8 |
9 | 'generate': function () {
10 | return new Promise(function (resolve, reject) {
11 | hexo.init().then(function () {
12 | hexo.call('generate', {force: true}).then(resolve, reject);
13 | });
14 | });
15 | }
16 |
17 | };
18 |
--------------------------------------------------------------------------------
/.documents/whiteboard/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "whiteboard",
3 | "version": "1.1.0",
4 | "license": "Apache-2.0",
5 | "main": "lib/whiteboard",
6 | "hexo": {
7 | "version": "3.9.0"
8 | },
9 | "dependencies": {
10 | "bluebird": "^3.5.5",
11 | "cheerio": "^1.0.0-rc.3",
12 | "hexo": "^3.9.0",
13 | "hexo-cli": "^2.0.0",
14 | "hexo-generator-archive": "^0.1.5",
15 | "hexo-generator-category": "^0.1.3",
16 | "hexo-generator-index": "^0.2.1",
17 | "hexo-generator-tag": "^0.2.0",
18 | "hexo-renderer-ejs": "^0.3.1",
19 | "hexo-renderer-stylus": "^0.3.3",
20 | "hexo-renderer-marked": "^1.0.1",
21 | "hexo-server": "^0.3.3"
22 | },
23 | "scripts": {
24 | "start": "hexo server",
25 | "generate": "hexo generate"
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/.documents/whiteboard/source/images/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/euclid1990/laravel/19a5b008c5649aef143b988c233c4fcfbb88557f/.documents/whiteboard/source/images/logo.png
--------------------------------------------------------------------------------
/.documents/whiteboard/source/images/navbar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/euclid1990/laravel/19a5b008c5649aef143b988c233c4fcfbb88557f/.documents/whiteboard/source/images/navbar.png
--------------------------------------------------------------------------------
/.documents/whiteboard/source/includes/_errors.md:
--------------------------------------------------------------------------------
1 | # Errors
2 |
3 |
4 |
5 | The Kittn API uses the following error codes:
6 |
7 |
8 | Error Code | Meaning
9 | ---------- | -------
10 | 400 | Bad Request -- Your request sucks
11 | 401 | Unauthorized -- Your API key is wrong
12 | 403 | Forbidden -- The kitten requested is hidden for administrators only
13 | 404 | Not Found -- The specified kitten could not be found
14 | 405 | Method Not Allowed -- You tried to access a kitten with an invalid method
15 | 406 | Not Acceptable -- You requested a format that isn't json
16 | 410 | Gone -- The kitten requested has been removed from our servers
17 | 418 | I'm a teapot
18 | 429 | Too Many Requests -- You're requesting too many kittens! Slow down!
19 | 500 | Internal Server Error -- We had a problem with our server. Try again later.
20 | 503 | Service Unavailable -- We're temporarily offline for maintenance. Please try again later.
21 |
--------------------------------------------------------------------------------
/.documents/whiteboard/source/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: SUNOS API Reference
3 |
4 | includes:
5 | - authenticate
6 | - errors
7 |
8 | search: true
9 | ---
10 |
--------------------------------------------------------------------------------
/.documents/whiteboard/themes/whiteboard/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | tmp
--------------------------------------------------------------------------------
/.documents/whiteboard/themes/whiteboard/_config.yml:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/euclid1990/laravel/19a5b008c5649aef143b988c233c4fcfbb88557f/.documents/whiteboard/themes/whiteboard/_config.yml
--------------------------------------------------------------------------------
/.documents/whiteboard/themes/whiteboard/scripts/highlight.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var cheerio;
4 |
5 | hexo.extend.filter.register('after_render:html', function(str, data){
6 | if (!cheerio) cheerio = require('cheerio');
7 | var $ = cheerio.load(str, {decodeEntities: false});
8 |
9 | $('figure.highlight').each(function(){
10 | var code = $(this).find('.code > pre').html();
11 | var html = '
' + code + '
';
12 | $(this).replaceWith(html)
13 | });
14 |
15 | $('pre > code').each(function(){
16 | if( !$(this).hasClass('highlight') ){
17 | $(this).addClass('highlight');
18 | }
19 | });
20 |
21 | return $.html();
22 | });
23 |
--------------------------------------------------------------------------------
/.documents/whiteboard/themes/whiteboard/scripts/read.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var fs = require('fs');
4 | var pathFn = require('path');
5 |
6 | hexo.extend.helper.register('read', function(path){
7 | var src = pathFn.join(hexo.source_dir, 'includes', pathFn.join(pathFn.dirname(path), '_' + pathFn.basename(path) + '.md'));
8 | if( fs.existsSync(src) ) {
9 | return fs.readFileSync(src, {
10 | encoding: 'utf-8'
11 | });
12 | }
13 | return '';
14 | });
15 |
--------------------------------------------------------------------------------
/.documents/whiteboard/themes/whiteboard/source/css/_icon_font.styl:
--------------------------------------------------------------------------------
1 | @font-face
2 | font-family: FontAwesome
3 | font-style: normal
4 | font-weight: normal
5 | src: url($font-icon-path + ".eot?v=#" + $font-icon-version)
6 | src: url($font-icon-path + ".eot?#iefix&v=#" + $font-icon-version) format("embedded-opentype"),
7 | url($font-icon-path + ".woff?v=#" + $font-icon-version) format("woff"),
8 | url($font-icon-path + ".ttf?v=#" + $font-icon-version) format("truetype"),
9 | url($font-icon-path + ".svg#fontawesomeregular?v=#" + $font-icon-version) format("svg")
10 |
11 | $icon
12 | font-family: 'FontAwesome'
13 | speak: none
14 | font-style: normal
15 | font-weight: normal
16 | font-variant: normal
17 | text-transform: none
18 | line-height: 1
19 |
20 | $icon-exclamation-sign
21 | @extend $icon
22 | content: "\f06a"
23 |
24 | $icon-info-sign
25 | @extend $icon
26 | content: "\f05a"
27 |
28 | $icon-ok-sign
29 | @extend $icon
30 | content: "\f058"
31 |
32 | $icon-search
33 | @extend $icon
34 | content: "\f002"
35 |
--------------------------------------------------------------------------------
/.documents/whiteboard/themes/whiteboard/source/css/_monokai.css:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | Monokai Sublime style. Derived from Monokai by noformnocontent http://nn.mit-license.org/
4 |
5 | */
6 |
7 | .hljs {
8 | display: block;
9 | overflow-x: auto;
10 | padding: 0.5em;
11 | background: #23241f;
12 | }
13 |
14 | .hljs,
15 | .hljs-tag,
16 | .hljs-subst {
17 | color: #f8f8f2;
18 | }
19 |
20 | .hljs-strong,
21 | .hljs-emphasis {
22 | color: #a8a8a2;
23 | }
24 |
25 | .hljs-bullet,
26 | .hljs-quote,
27 | .hljs-number,
28 | .hljs-regexp,
29 | .hljs-literal,
30 | .hljs-link {
31 | color: #ae81ff;
32 | }
33 |
34 | .hljs-code,
35 | .hljs-title,
36 | .hljs-section,
37 | .hljs-selector-class {
38 | color: #a6e22e;
39 | }
40 |
41 | .hljs-strong {
42 | font-weight: bold;
43 | }
44 |
45 | .hljs-emphasis {
46 | font-style: italic;
47 | }
48 |
49 | .hljs-keyword,
50 | .hljs-selector-tag,
51 | .hljs-name,
52 | .hljs-attr {
53 | color: #f92672;
54 | }
55 |
56 | .hljs-symbol,
57 | .hljs-attribute {
58 | color: #66d9ef;
59 | }
60 |
61 | .hljs-params,
62 | .hljs-class .hljs-title {
63 | color: #f8f8f2;
64 | }
65 |
66 | .hljs-string,
67 | .hljs-type,
68 | .hljs-built_in,
69 | .hljs-builtin-name,
70 | .hljs-selector-id,
71 | .hljs-selector-attr,
72 | .hljs-selector-pseudo,
73 | .hljs-addition,
74 | .hljs-variable,
75 | .hljs-template-variable {
76 | color: #e6db74;
77 | }
78 |
79 | .hljs-comment,
80 | .hljs-deletion,
81 | .hljs-meta {
82 | color: #75715e;
83 | }
84 |
--------------------------------------------------------------------------------
/.documents/whiteboard/themes/whiteboard/source/css/fonts/FontAwesome.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/euclid1990/laravel/19a5b008c5649aef143b988c233c4fcfbb88557f/.documents/whiteboard/themes/whiteboard/source/css/fonts/FontAwesome.otf
--------------------------------------------------------------------------------
/.documents/whiteboard/themes/whiteboard/source/css/fonts/fontawesome-webfont.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/euclid1990/laravel/19a5b008c5649aef143b988c233c4fcfbb88557f/.documents/whiteboard/themes/whiteboard/source/css/fonts/fontawesome-webfont.eot
--------------------------------------------------------------------------------
/.documents/whiteboard/themes/whiteboard/source/css/fonts/fontawesome-webfont.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/euclid1990/laravel/19a5b008c5649aef143b988c233c4fcfbb88557f/.documents/whiteboard/themes/whiteboard/source/css/fonts/fontawesome-webfont.ttf
--------------------------------------------------------------------------------
/.documents/whiteboard/themes/whiteboard/source/css/fonts/fontawesome-webfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/euclid1990/laravel/19a5b008c5649aef143b988c233c4fcfbb88557f/.documents/whiteboard/themes/whiteboard/source/css/fonts/fontawesome-webfont.woff
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | charset = utf-8
5 | end_of_line = lf
6 | insert_final_newline = true
7 | indent_style = space
8 | indent_size = 4
9 | trim_trailing_whitespace = true
10 |
11 | [*.md]
12 | trim_trailing_whitespace = false
13 |
14 | [*.yml]
15 | indent_size = 2
16 |
--------------------------------------------------------------------------------
/.env.dev.example:
--------------------------------------------------------------------------------
1 | APP_NAME=Laravel
2 | APP_ENV=local
3 | APP_KEY=
4 | APP_DEBUG=true
5 | APP_URL=https://localhost:8443
6 | APP_VERSION=
7 |
8 | LOG_CHANNEL=stack
9 |
10 | DB_CONNECTION=mysql
11 | DB_HOST=mysql
12 | DB_PORT=3306
13 | DB_DATABASE=ms_database
14 | DB_USERNAME=ms_user
15 | DB_PASSWORD=ms_password
16 |
17 | BROADCAST_DRIVER=log
18 | CACHE_DRIVER=file
19 | QUEUE_CONNECTION=redis
20 | SESSION_DRIVER=file
21 | SESSION_LIFETIME=120
22 |
23 | REDIS_HOST=redis
24 | REDIS_PASSWORD=rd_password
25 | REDIS_PORT=6379
26 |
27 | MEMCACHED_PERSISTENT_ID=memcached
28 | MEMCACHED_HOST=memcached
29 | MEMCACHED_PORT=11211
30 | MEMCACHED_USERNAME=mem_user
31 | MEMCACHED_PASSWORD=mem_password
32 |
33 | MAIL_DRIVER=smtp
34 | MAIL_HOST=smtp.mailtrap.io
35 | MAIL_PORT=2525
36 | MAIL_USERNAME=null
37 | MAIL_PASSWORD=null
38 | MAIL_ENCRYPTION=null
39 |
40 | AWS_ACCESS_KEY_ID=
41 | AWS_SECRET_ACCESS_KEY=
42 | AWS_DEFAULT_REGION=us-east-1
43 | AWS_BUCKET=
44 |
45 | PUSHER_APP_ID=
46 | PUSHER_APP_KEY=
47 | PUSHER_APP_SECRET=
48 | PUSHER_APP_CLUSTER=mt1
49 |
50 | MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
51 | MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
52 |
53 | API_CLIENT_ID=
54 | API_CLIENT_SECRET=
55 |
56 | MIX_BASE_URL="${APP_URL}"
57 | MIX_BASIC_AUTHEN="web:123456"
58 | MIX_API_PREFIX="api"
59 | MIX_API_VERSION="v1"
60 |
61 | CHATWORK_API_KEY=""
62 | CHATWORK_ROOM_ID=""
63 | SLACK_HOOK=""
64 |
--------------------------------------------------------------------------------
/.env.example:
--------------------------------------------------------------------------------
1 | APP_NAME=Laravel
2 | APP_ENV=local
3 | APP_KEY=
4 | APP_DEBUG=true
5 | APP_URL=http://localhost
6 | APP_VERSION=
7 |
8 | LOG_CHANNEL=stack
9 |
10 | DB_CONNECTION=mysql
11 | DB_HOST=127.0.0.1
12 | DB_PORT=3306
13 | DB_DATABASE=homestead
14 | DB_USERNAME=homestead
15 | DB_PASSWORD=secret
16 |
17 | BROADCAST_DRIVER=log
18 | CACHE_DRIVER=file
19 | QUEUE_CONNECTION=sync
20 | SESSION_DRIVER=file
21 | SESSION_LIFETIME=120
22 |
23 | REDIS_HOST=127.0.0.1
24 | REDIS_PASSWORD=null
25 | REDIS_PORT=6379
26 |
27 | MAIL_DRIVER=smtp
28 | MAIL_HOST=smtp.mailtrap.io
29 | MAIL_PORT=2525
30 | MAIL_USERNAME=null
31 | MAIL_PASSWORD=null
32 | MAIL_ENCRYPTION=null
33 |
34 | AWS_ACCESS_KEY_ID=
35 | AWS_SECRET_ACCESS_KEY=
36 | AWS_DEFAULT_REGION=us-east-1
37 | AWS_BUCKET=
38 |
39 | PUSHER_APP_ID=
40 | PUSHER_APP_KEY=
41 | PUSHER_APP_SECRET=
42 | PUSHER_APP_CLUSTER=mt1
43 |
44 | MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
45 | MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
46 |
47 | MIX_BASE_URL="${APP_URL}"
48 | MIX_BASIC_AUTHEN="web:123456"
49 | MIX_API_PREFIX="api"
50 | MIX_API_VERSION="v1"
51 |
52 | CHATWORK_API_KEY=""
53 | CHATWORK_ROOM_ID=""
54 | SLACK_HOOK=""
55 |
--------------------------------------------------------------------------------
/.envs/dev/cert/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM ubuntu:18.04
2 |
3 | ENV DEBIAN_FRONTEND noninteractive
4 | ENV USERID=1001 GROUPID=1001
5 |
6 | # Install os packages
7 | RUN apt-get update && apt-get install -y \
8 | sudo \
9 | openssl \
10 | apache2-utils \
11 | --no-install-recommends apt-utils \
12 | && rm -r /var/lib/apt/lists/*
13 |
14 | COPY cert/rootCA.csr.cnf /scripts/
15 |
16 | COPY cert/v3.ext /scripts/
17 |
18 | COPY cert/*.sh /scripts/
19 |
20 | RUN chmod a+x /scripts/*.sh
21 |
22 | RUN mkdir /files
23 |
24 | # Create new username: cert
25 | RUN useradd -ms /bin/bash cert --no-log-init
26 | # Modify cert user_id:group_id to current host_user_id:host_group_id
27 | RUN usermod -u $USERID cert
28 | RUN groupmod -g $GROUPID cert
29 |
30 | # Set user to running image
31 | USER root
32 |
33 | ENTRYPOINT ["sh", "/scripts/entrypoint.sh"]
34 |
35 | CMD ["/scripts/command.sh", "localhost"]
36 |
--------------------------------------------------------------------------------
/.envs/dev/cert/command.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | DOMAIN=${1:-localhost}
4 |
5 | if [[ ! -f "/files/${DOMAIN}.crt" ]]; then
6 | /scripts/create-rootCA.sh
7 | /scripts/create-certs.sh $DOMAIN
8 | fi
9 |
10 | if [[ ! -f "/files/.htpasswd" ]]; then
11 | /scripts/create-htpasswd.sh
12 | fi
13 |
14 |
--------------------------------------------------------------------------------
/.envs/dev/cert/create-certs.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Create a new private key if one doesnt exist, or use the xeisting one if it does
4 | DOMAIN=$1
5 | NUM_OF_DAYS=999
6 |
7 | openssl req -new -sha256 -nodes -out "/files/$DOMAIN.csr" -newkey rsa:2048 -keyout "/files/$DOMAIN.key" -config /scripts/rootCA.csr.cnf
8 | cat /scripts/v3.ext | sed s/%%DOMAIN%%/"$DOMAIN"/g > /tmp/__v3.ext
9 | openssl x509 -req -in "/files/$DOMAIN.csr" -CA /files/rootCA.pem -CAkey /files/rootCA.key -CAcreateserial -out "/files/$DOMAIN.crt" -days $NUM_OF_DAYS -sha256 -extfile /tmp/__v3.ext
10 | rm /tmp/__v3.ext
11 |
--------------------------------------------------------------------------------
/.envs/dev/cert/create-htpasswd.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | htpasswd -b -c /files/.htpasswd $HT_USER $HT_PASSWORD
4 |
--------------------------------------------------------------------------------
/.envs/dev/cert/create-rootCA.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Create CA key and cert
4 | openssl genrsa -out /files/rootCA.key 2048
5 | openssl req -subj "/C=VN/ST=Hanoi/L=Hanoi/O=MyCompany/OU=Division/emailAddress=admin@example.com/CN=Localhost Certification Authority" \
6 | -x509 -new -nodes -key /files/rootCA.key -sha256 -days 1024 -out /files/rootCA.pem
7 |
--------------------------------------------------------------------------------
/.envs/dev/cert/entrypoint.sh:
--------------------------------------------------------------------------------
1 | # Change owner of /files directory to user cert
2 | chown -R cert:cert /files
3 | exec runuser -u cert "$@"
4 |
--------------------------------------------------------------------------------
/.envs/dev/cert/files/.gitignore:
--------------------------------------------------------------------------------
1 | *
2 | !.gitignore
3 |
--------------------------------------------------------------------------------
/.envs/dev/cert/rootCA.csr.cnf:
--------------------------------------------------------------------------------
1 | [req]
2 | default_bits = 2048
3 | prompt = no
4 | default_md = sha256
5 | distinguished_name = dn
6 |
7 | [dn]
8 | C=VN
9 | ST=Hanoi
10 | L=Hanoi
11 | O=MyCompany
12 | OU=Division
13 | emailAddress=admin@example.com
14 | CN=Localhost Certification Authority
15 |
--------------------------------------------------------------------------------
/.envs/dev/cert/v3.ext:
--------------------------------------------------------------------------------
1 | authorityKeyIdentifier=keyid,issuer
2 | basicConstraints=CA:FALSE
3 | keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
4 | subjectAltName = @alt_names
5 |
6 | [alt_names]
7 | DNS.1 = %%DOMAIN%%
8 |
--------------------------------------------------------------------------------
/.envs/dev/memcached/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM memcached:1.5.12
2 |
--------------------------------------------------------------------------------
/.envs/dev/mysql/.gitignore:
--------------------------------------------------------------------------------
1 | /data
2 |
--------------------------------------------------------------------------------
/.envs/dev/mysql/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM mysql:5.7
2 |
3 | RUN apt-get update && \
4 | apt-get install -y vim sudo \
5 | --no-install-recommends apt-utils \
6 | && rm -r /var/lib/apt/lists/*
7 |
8 | COPY mysql/entrypoint.sh /usr/local/bin/docker-entrypoint.sh
9 |
10 | RUN chmod a+x /usr/local/bin/docker-entrypoint.sh
11 |
12 | RUN rm /entrypoint.sh
13 |
14 | RUN ln -s /usr/local/bin/docker-entrypoint.sh /entrypoint.sh # backward compatibility
15 |
16 | ENTRYPOINT ["docker-entrypoint.sh"]
17 |
18 | EXPOSE 3306 33060
19 |
20 | CMD ["mysqld"]
21 |
--------------------------------------------------------------------------------
/.envs/dev/nginx/.gitignore:
--------------------------------------------------------------------------------
1 | *.log
2 |
--------------------------------------------------------------------------------
/.envs/dev/nginx/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM nginx:1.15.11
2 |
3 | # Install os packages
4 | RUN apt-get update && apt-get install -y \
5 | vim \
6 | curl \
7 | && rm -r /var/lib/apt/lists/*
8 |
9 | COPY nginx/*.sh /scripts/
10 |
11 | COPY common/wait-for-it.sh /scripts/
12 |
13 | RUN chmod a+x /scripts/*.sh
14 |
15 | EXPOSE 80 443
16 |
17 | CMD ["/scripts/command.sh"]
18 |
--------------------------------------------------------------------------------
/.envs/dev/nginx/command.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | until [[ -f /etc/nginx/certs/localhost.crt && -f /etc/nginx/certs/localhost.key && -f /etc/nginx/certs/.htpasswd ]]; do
4 | echo "Waiting for self-certificates existing..."
5 | sleep 1
6 | done
7 |
8 | /scripts/wait-for-it.sh php:9000 --timeout=300 -- echo 'PHP service is ready!'
9 |
10 | nginx -g 'daemon off;'
11 |
--------------------------------------------------------------------------------
/.envs/dev/nginx/conf.d/default.conf:
--------------------------------------------------------------------------------
1 | server {
2 | listen 80;
3 | listen [::]:80;
4 | server_name _;
5 | return 301 https://$host:8443$request_uri;
6 | }
7 |
8 | server {
9 | error_log /var/www/app/.envs/dev/nginx/logs/error.log;
10 | access_log /var/www/app/.envs/dev/nginx/logs/access.log;
11 |
12 | satisfy any;
13 | # Add basic authentication use auth_basic setting
14 | auth_basic "Staging's Area";
15 | auth_basic_user_file /etc/nginx/certs/.htpasswd;
16 | # IP whitelist
17 | include /etc/nginx/conf.d/ip-whitelist.conf;
18 | deny all;
19 |
20 | listen 443 ssl default_server;
21 | listen [::]:443 ssl default_server ;
22 | server_name localhost;
23 |
24 | # SSL certificates
25 | ssl_certificate /etc/nginx/certs/localhost.crt;
26 | ssl_certificate_key /etc/nginx/certs/localhost.key;
27 |
28 | # Recommendations from https://raymii.org/s/tutorials/Strong_SSL_Security_On_nginx.html
29 | ssl_ciphers EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH;
30 | ssl_protocols TLSv1.1 TLSv1.2;
31 | ssl_prefer_server_ciphers on;
32 | ssl_session_cache shared:SSL:10m;
33 |
34 | # Disable any limits to avoid HTTP 413 for large image uploads
35 | client_max_body_size 0;
36 |
37 | # Laravel directory
38 | root /var/www/app/public;
39 | index index.php index.html index.htm;
40 |
41 | # Nginx will reject anything not matching /
42 | location / {
43 | try_files $uri $uri/ /index.php$is_args$args;
44 | }
45 |
46 | location ~ \.php$ {
47 | fastcgi_split_path_info ^(.+?\.php)(/.*)$;
48 | if (!-f $document_root$fastcgi_script_name) {
49 | return 404;
50 | }
51 | include fastcgi_params;
52 | fastcgi_pass php-fpm;
53 | fastcgi_index index.php;
54 | fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
55 | fastcgi_param DOCUMENT_ROOT $realpath_root;
56 | fastcgi_param HTTP_AUTHORIZATION $http_authorization_bearer;
57 | fastcgi_param HTTP_AUTHORIZATION_BEARER '';
58 | fastcgi_param REALPATHTEST $realpath_root;
59 | internal;
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/.envs/dev/nginx/conf.d/documents.conf:
--------------------------------------------------------------------------------
1 | upstream documents {
2 | server node:4000;
3 | }
4 |
5 | server {
6 | listen 445 ssl;
7 | listen [::]:445 ssl ;
8 | server_name documents;
9 |
10 | # SSL certificates
11 | ssl_certificate /etc/nginx/certs/localhost.crt;
12 | ssl_certificate_key /etc/nginx/certs/localhost.key;
13 |
14 | # Recommendations from https://raymii.org/s/tutorials/Strong_SSL_Security_On_nginx.html
15 | ssl_ciphers EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH;
16 | ssl_protocols TLSv1.1 TLSv1.2;
17 | ssl_prefer_server_ciphers on;
18 | ssl_session_cache shared:SSL:10m;
19 |
20 | location / {
21 | proxy_pass http://documents;
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/.envs/dev/nginx/conf.d/ip-whitelist.conf:
--------------------------------------------------------------------------------
1 | # Company's Global IP List
2 | allow 192.168.1.1;
3 | # Customer's Global IP List
4 | allow 192.168.1.2;
--------------------------------------------------------------------------------
/.envs/dev/nginx/conf.d/phpmyadmin.conf:
--------------------------------------------------------------------------------
1 | server {
2 | listen 444 ssl;
3 | listen [::]:444 ssl ;
4 | server_name phpmyadmin;
5 |
6 | # SSL certificates
7 | ssl_certificate /etc/nginx/certs/localhost.crt;
8 | ssl_certificate_key /etc/nginx/certs/localhost.key;
9 |
10 | # Recommendations from https://raymii.org/s/tutorials/Strong_SSL_Security_On_nginx.html
11 | ssl_ciphers EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH;
12 | ssl_protocols TLSv1.1 TLSv1.2;
13 | ssl_prefer_server_ciphers on;
14 | ssl_session_cache shared:SSL:10m;
15 |
16 | # Phpmyadmin directory
17 | root /var/www/app/.envs/dev/phpmyadmin/src/phpMyAdmin-4.8.5;
18 |
19 | index index.php index.html index.htm;
20 |
21 | location / {
22 | index index.html index.htm index.php
23 | try_files $uri /index.php$is_args$args;
24 | }
25 |
26 | location ~ ^/.+\.php(/|$) {
27 | fastcgi_split_path_info ^(.+?\.php)(/.*)$;
28 | if (!-f $document_root$fastcgi_script_name) {
29 | return 404;
30 | }
31 | include fastcgi_params;
32 | fastcgi_pass php-fpm;
33 | fastcgi_index index.php;
34 | fastcgi_param SCRIPT_FILENAME $document_root/$fastcgi_script_name;
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/.envs/dev/nginx/logs/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/euclid1990/laravel/19a5b008c5649aef143b988c233c4fcfbb88557f/.envs/dev/nginx/logs/.gitkeep
--------------------------------------------------------------------------------
/.envs/dev/nginx/nginx.conf:
--------------------------------------------------------------------------------
1 | user nginx;
2 | # Number workers to spawn once it has become bound to the proper IP and port
3 | worker_processes 1;
4 |
5 | error_log /var/log/nginx/error.log warn;
6 | pid /var/run/nginx.pid;
7 |
8 | events {
9 | # Nginx can server 1024 clients/second
10 | worker_connections 1024;
11 | }
12 |
13 | http {
14 | include /etc/nginx/mime.types;
15 | default_type application/octet-stream;
16 |
17 | log_format main '$remote_addr - $remote_user [$time_local] "$request" '
18 | '$status $body_bytes_sent "$http_referer" '
19 | '"$http_user_agent" "$http_x_forwarded_for"';
20 |
21 | access_log /var/log/nginx/access.log main;
22 |
23 | # Nginx will handle gzip compression of responses from the app server
24 | gzip on;
25 | gzip_comp_level 2;
26 | gzip_proxied any;
27 | gzip_types text/plain application/json;
28 | gzip_min_length 1000;
29 | charset utf-8;
30 | sendfile off;
31 | keepalive_timeout 65;
32 |
33 | # PHP-FPM reverse proxy
34 | upstream php-fpm {
35 | server php:9000;
36 | }
37 |
38 | include /etc/nginx/conf.d/*.conf;
39 | }
40 |
--------------------------------------------------------------------------------
/.envs/dev/node/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM node:10.15.3-stretch
2 |
3 | COPY node/*.sh /scripts/
4 |
5 | RUN chmod a+x /scripts/*.sh
6 |
7 | EXPOSE 80 443
8 |
9 | CMD ["/scripts/command.sh"]
10 |
--------------------------------------------------------------------------------
/.envs/dev/node/command.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | yarn install
4 |
5 | # Sleep untils backend api endpoint existing
6 | while [ ! -f /var/www/app/resources/js/endpoint.js ]
7 | do
8 | sleep 3
9 | done
10 |
11 | yarn run dev
12 |
13 | yarn run documents
14 |
15 | sleep infinity
16 |
--------------------------------------------------------------------------------
/.envs/dev/php/command.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | /scripts/wait-for-it.sh mysql:3306 --timeout=300 -- echo 'Mysql service is ready!'
4 |
5 | /scripts/passport.sh
6 |
7 | php-fpm
8 |
--------------------------------------------------------------------------------
/.envs/dev/php/crontab/cron.daily.logrotate:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | test -x /usr/sbin/logrotate || exit 0
4 | /usr/sbin/logrotate -f /etc/logrotate.conf
5 |
--------------------------------------------------------------------------------
/.envs/dev/php/crontab/cron.minutely.schedule:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | test -x php /var/www/app/artisan || exit 0
4 | php /var/www/app/artisan schedule:run >> /dev/null 2>&1
5 |
--------------------------------------------------------------------------------
/.envs/dev/php/crontab/crontab:
--------------------------------------------------------------------------------
1 | # /etc/crontab: system-wide crontab
2 | # Unlike any other crontab you don't have to run the `crontab'
3 | # command to install the new version when you edit this file
4 | # and files in /etc/cron.d. These files also have username fields,
5 | # that none of the other crontabs do.
6 |
7 | SHELL=/bin/sh
8 | PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
9 |
10 | # m h dom mon dow user command
11 | * * * * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.minutely )
12 | 15 * * * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.hourly )
13 | 30 10 * * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )
14 | 40 10 * * 7 root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly )
15 | 50 10 1 * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly )
16 | #
17 |
--------------------------------------------------------------------------------
/.envs/dev/php/entrypoint.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Copy development environment file if not existing
4 | if [[ ! -f /var/www/app/.env && -f /var/www/app/.env.dev.example ]]; then
5 | cp /var/www/app/.env.dev.example /var/www/app/.env
6 | fi
7 |
8 | # Generate application key if it not set
9 | APP_KEY=$(cat .env | sed -n 's/^APP_KEY=/ /p')
10 | if [[ -z "${APP_KEY// }" ]]; then
11 | php artisan key:generate
12 | fi
13 |
14 | vendorDir=/var/www/app/vendor
15 | # Install composer if it not existing
16 | if [[ ! -d $vendorDir ]]; then
17 | composer install
18 | fi
19 |
20 | vendorOwner=$(stat -c '%U' $vendorDir)
21 | if [ "$vendorOwer" != "php-fpm" ]; then
22 | # Change owner of $vendorDir directory to user php-fpm
23 | sudo chown -R php-fpm:php-fpm $vendorDir
24 | fi
25 |
26 | standardPath=/var/www/app/vendor/squizlabs/php_codesniffer/src/Standards/SunOS
27 | if [ ! -d "$standardPath" ]; then
28 | # Copy php code sniff to vendor
29 | cp -i -r .envs/dev/phpcs/SunOS/ $standardPath
30 | fi
31 |
32 | # Discovery new packages and generate manifest
33 | composer dump-autoload
34 |
35 | # Generate application routes for client
36 | php artisan laroute:generate
37 |
38 | # Starting Supervisor to start the queue process
39 | sudo /etc/init.d/supervisor start
40 |
41 | exec "$@"
42 |
--------------------------------------------------------------------------------
/.envs/dev/php/passport.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | if [ $(cat ./.env | grep "API_CLIENT_ID") == "API_CLIENT_ID=" ] || [ $(cat ./.env | grep "API_CLIENT_SECRET") == "API_CLIENT_SECRET=" ]; then
4 | echo "---GENERATING PASSPORT CLIENT ID & SECRET.---"
5 |
6 | passport=$(php artisan passport:client --password --no-interaction)
7 | clientId=$(expr match "$passport" '.*\(Client ID: [[:digit:]]*\)')
8 | clientSecret=$(expr match "$passport" '.*\(Client secret: [[:alnum:]]*\)')
9 |
10 | clientId=${clientId:11}
11 | clientSecret=${clientSecret:15}
12 |
13 | sed -i "s/API_CLIENT_ID=.*/API_CLIENT_ID=$clientId/g" .env
14 | sed -i "s/API_CLIENT_SECRET=.*/API_CLIENT_SECRET=$clientSecret/g" .env
15 |
16 | echo "---PASSPORT CLIENT ID & SECRET IS GENERATED.---"
17 | fi
18 |
--------------------------------------------------------------------------------
/.envs/dev/php/php-worker:
--------------------------------------------------------------------------------
1 | /var/www/app/storage/logs/worker.log {
2 | daily
3 | rotate 30
4 | copytruncate
5 | missingok
6 | notifempty
7 | dateext
8 | sharedscripts
9 | postrotate
10 | dir=/var/www/app/storage/logs
11 | day=$(date +%Y%m%d)
12 | dayNew=$(date +%Y-%m-%d)
13 | mv $dir/worker.log-$day $dir/worker-$dayNew.log
14 | endscript
15 | }
16 |
--------------------------------------------------------------------------------
/.envs/dev/php/php-worker.conf:
--------------------------------------------------------------------------------
1 | [program:cron]
2 | autorestart=false
3 | command=cron -f
4 |
5 | [program:php-worker]
6 | process_name=%(program_name)s_%(process_num)02d
7 | command=php /var/www/app/artisan queue:work redis --sleep=3 --tries=1 --timeout=180
8 | autostart=true
9 | autorestart=true
10 | user=php-fpm
11 | numprocs=1
12 | redirect_stderr=true
13 | stdout_logfile=/var/www/app/storage/logs/worker.log
14 | stdout_logfile_backups=0
15 | stdout_logfile_maxbytes=0
16 |
17 | [program:php-monitor]
18 | process_name=%(program_name)s_%(process_num)02d
19 | command=php /var/www/app/artisan queue:work redis --queue=monitor --sleep=3 --tries=1 --timeout=180
20 | autostart=true
21 | autorestart=true
22 | user=php-fpm
23 | numprocs=1
24 | redirect_stderr=true
25 | stdout_logfile=/var/www/app/storage/logs/monitor.log
26 | stdout_logfile_backups=0
27 | stdout_logfile_maxbytes=0
28 |
--------------------------------------------------------------------------------
/.envs/dev/phpcs/SunOS/ruleset.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | The SunOS Coding Standard package for Code Sniffer.
4 | .documents
5 | .circleci
6 | .github
7 | .envs
8 | public
9 | bootstrap
10 | storage
11 | resources
12 | vendor
13 | node_modules
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/.envs/dev/phpmyadmin/command.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | if [ ! -d "src/phpMyAdmin-4.8.5" ]; then
4 | echo "------ [BEGIN] Extract PhpMyAdmin Source Code ------"
5 | tar -zxf phpMyAdmin-4.8.5.tar.gz -C src/
6 | echo "------ [END] Extract PhpMyAdmin Source Code ------"
7 | fi
8 |
--------------------------------------------------------------------------------
/.envs/dev/phpmyadmin/phpMyAdmin-4.8.5.tar.gz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/euclid1990/laravel/19a5b008c5649aef143b988c233c4fcfbb88557f/.envs/dev/phpmyadmin/phpMyAdmin-4.8.5.tar.gz
--------------------------------------------------------------------------------
/.envs/dev/phpmyadmin/src/.gitignore:
--------------------------------------------------------------------------------
1 | *
2 | !.gitignore
3 |
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | public/**/*.js
3 | vendor
4 | resources/js/endpoint.js
5 |
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | 'extends': [
3 | 'standard',
4 | 'plugin:vue/recommended'
5 | ],
6 | 'parser': 'vue-eslint-parser',
7 | 'parserOptions': {
8 | "parser": "babel-eslint",
9 | 'ecmaVersion': 2017,
10 | 'sourceType': 'module',
11 | 'ecmaFeatures': {
12 | 'jsx': true,
13 | legacyDecorators: true
14 | }
15 | },
16 | 'rules': {
17 | 'indent': ['error', 2],
18 | 'quotes': ['warn', 'single'],
19 | 'semi': [1, 'never'],
20 | 'space-before-function-paren': ['error', {
21 | 'anonymous': 'never',
22 | 'named': 'never',
23 | 'asyncArrow': 'always'
24 | }],
25 | 'no-useless-constructor': 'off',
26 | 'no-unused-vars': 'warn',
27 | 'no-new': 'warn',
28 | 'new-cap': 'off',
29 | 'eol-last': ['error', 'always']
30 | },
31 | "globals": {
32 | "workbox": true
33 | }
34 | };
35 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | * text=auto
2 | *.css linguist-vendored
3 | *.scss linguist-vendored
4 | *.js linguist-vendored
5 | CHANGELOG.md export-ignore
6 |
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | ## 1. Task Link
2 |
3 |
4 |
5 | ## 2. What you did
6 |
7 |
11 |
12 | ## 3. Screen Shots
13 |
14 |
18 |
19 | ## 4. Checklists
20 |
21 | - [ ] Did you read task requirement?
22 | - [ ] Did you confirm task related question with Team Lead or Brse?
23 | - [ ] Did you check UI is as same as design?
24 | - [ ] Did you check Web behavior as same as requirements? 💣
25 | - [ ] Did you implement and run unit testing? 💣
26 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /node_modules
2 | /public/hot
3 | /public/storage
4 | /public/mix-manifest.json
5 | /storage/*.key
6 | /resources/js/endpoint.js
7 | /vendor
8 | .env
9 | .phpintel
10 | .phpunit.result.cache
11 | Homestead.json
12 | Homestead.yaml
13 | npm-debug.log
14 | yarn-error.log
15 | .DS_Store
16 | docker-compose.yml
17 | public/examples
18 | reports
19 | package-lock.json
20 | .idea
21 | /coverage
22 |
--------------------------------------------------------------------------------
/.stylelintignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | public/**/*.css
3 |
--------------------------------------------------------------------------------
/.stylelintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | 'extends': 'stylelint-config-standard',
3 | 'plugins': [
4 | 'stylelint-scss'
5 | ],
6 | 'rules': {
7 | 'indentation': 2,
8 | 'at-rule-empty-line-before': null,
9 | 'unit-no-unknown': [ true, { 'ignoreUnits': ['x'] }],
10 | 'no-empty-source': null,
11 | 'at-rule-no-unknown': null,
12 | 'scss/at-rule-no-unknown': true
13 | }
14 | };
15 |
--------------------------------------------------------------------------------
/app/Console/Commands/GitGetCommit.php:
--------------------------------------------------------------------------------
1 | writeNewEnvironmentFileWith($hash)) {
43 | return;
44 | }
45 |
46 | $this->info('App version set successfully.');
47 | }
48 |
49 | /**
50 | * Write a new environment file with the given key.
51 | *
52 | * @param string $key
53 | * @return void
54 | */
55 | protected function writeNewEnvironmentFileWith($version)
56 | {
57 | file_put_contents($this->laravel->environmentFilePath(), preg_replace(
58 | '/^APP_VERSION=(\s*|.+)$/m',
59 | 'APP_VERSION=' . $version,
60 | file_get_contents($this->laravel->environmentFilePath())
61 | ));
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/app/Console/Kernel.php:
--------------------------------------------------------------------------------
1 | command('inspire')
28 | // ->hourly();
29 | }
30 |
31 | /**
32 | * Register the commands for the application.
33 | *
34 | * @return void
35 | */
36 | protected function commands()
37 | {
38 | $this->load(__DIR__.'/Commands');
39 |
40 | require base_path('routes/console.php');
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/app/Exceptions/Api/ActionException.php:
--------------------------------------------------------------------------------
1 | data = $data;
31 | $this->statusCode = $statusCode;
32 | $this->description = $description;
33 |
34 | parent::__construct($description, $statusCode);
35 | }
36 |
37 | public function getErrorDescription()
38 | {
39 | return $this->getMessage();
40 | }
41 |
42 | public function getStatusCode()
43 | {
44 | return $this->statusCode;
45 | }
46 |
47 | public function getData()
48 | {
49 | return $this->data;
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/app/Exceptions/Api/NotFoundException.php:
--------------------------------------------------------------------------------
1 | $permissionName]));
12 | }
13 |
14 | public static function withId(int $permissionId)
15 | {
16 | return new InvalidArgumentException(__('exception.there_no_permission_id', ['permissionId' => $permissionId]));
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/app/Exceptions/Permission/RoleDoesNotExist.php:
--------------------------------------------------------------------------------
1 | $roleName]));
12 | }
13 |
14 | public static function withId(int $roleId)
15 | {
16 | return new InvalidArgumentException(__('exception.there_no_role_id', ['roleId' => $roleId]));
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/app/Exceptions/Permission/UnauthorizedException.php:
--------------------------------------------------------------------------------
1 | $permStr]);
14 |
15 | $exception = new static(Response::HTTP_FORBIDDEN, $message, null, []);
16 |
17 | return $exception;
18 | }
19 |
20 | public static function forPermissions($permissions): self
21 | {
22 | $permStr = implode(', ', $permissions);
23 | $message = __('exception.not_have_permission', ['permissions' => $permStr]);
24 |
25 | $exception = new static(Response::HTTP_FORBIDDEN, $message, null, []);
26 |
27 | return $exception;
28 | }
29 |
30 | public static function notLoggedIn(): self
31 | {
32 | return new static(Response::HTTP_FORBIDDEN, __('exception.not_loggin'), null, []);
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/app/Http/Controllers/Api/ApiController.php:
--------------------------------------------------------------------------------
1 | userService = $userService;
27 | $this->authService = $authService;
28 | }
29 |
30 | public function sendResetTokenEmail(ForgotPasswordRequest $request)
31 | {
32 | $email = $request->email;
33 | $updateToken = null;
34 | $user = $this->userService->getUserByEmail($email);
35 |
36 | if ($user) {
37 | $resetToken = $this->authService->generateResetToken($user);
38 |
39 | $this->authService->queueMailResetPassword($user, $resetToken);
40 |
41 | $updateToken = $this->authService->createResetPasswordToken($request->email, $resetToken);
42 | }
43 |
44 | return new AuthResource($updateToken, __FUNCTION__, __('passwords.sent'));
45 | }
46 |
47 | public function reset(ResetPasswordRequest $request)
48 | {
49 | $params = $request->only('password', 'token');
50 | $reset = $this->authService->resetPassword($params['password'], $params['token']);
51 |
52 | return new AuthResource($reset, 'resetPassword', __('passwords.reset'));
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/app/Http/Controllers/Api/UserController.php:
--------------------------------------------------------------------------------
1 | middleware('guest')->except('logout');
30 | $this->authService = $authService;
31 | }
32 |
33 | /**
34 | * Show the application's login form.
35 | *
36 | * @return \Illuminate\Http\Response
37 | */
38 | public function showLoginForm()
39 | {
40 | return view('auth.login');
41 | }
42 | /**
43 | * Handle a login request to the application.
44 | *
45 | * @param \App\Http\Requests\LoginRequest $request
46 | * @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\Response|\Illuminate\Http\JsonResponse
47 | *
48 | * @throws \Illuminate\Validation\ValidationException
49 | */
50 | public function login(LoginRequest $request)
51 | {
52 | if ($this->authService->attempt($request)) {
53 | $request->session()->regenerate();
54 |
55 | return redirect(route('home'));
56 | } else {
57 | throw ValidationException::withMessages([
58 | 'email' => [trans('auth.failed')],
59 | ]);
60 | }
61 | }
62 | /**
63 | * Log the user out of the application.
64 | *
65 | * @param \Illuminate\Http\Request $request
66 | * @return \Illuminate\Http\Response
67 | */
68 | public function logout(Request $request)
69 | {
70 | auth()->guard()->logout();
71 |
72 | $request->session()->invalidate();
73 |
74 | return redirect(route('home'));
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/app/Http/Controllers/Web/Auth/RegisterController.php:
--------------------------------------------------------------------------------
1 | middleware('guest');
42 | $this->userService = $userService;
43 | }
44 | /**
45 | * Show the application registration form.
46 | *
47 | * @return \Illuminate\Http\Response
48 | */
49 | public function showRegistrationForm()
50 | {
51 | return view('auth.register');
52 | }
53 | /**
54 | * Handle a registration request for the application.
55 | *
56 | * @param \App\Http\Requests\RegistersUsers $request
57 | * @return \Illuminate\Http\Response
58 | */
59 | public function register(RegisterRequest $request)
60 | {
61 | event(new Registered($user = $this->userService->store($request->all())));
62 |
63 | $this->guard()->login($user);
64 |
65 | return $this->registered($request, $user) ?: redirect($this->redirectPath());
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/app/Http/Controllers/Web/Auth/ResetPasswordController.php:
--------------------------------------------------------------------------------
1 | middleware('guest');
31 | $this->authService = $authService;
32 | }
33 |
34 | /**
35 | * Display the password reset view for the given token.
36 | *
37 | * If no token is present, display the link request form.
38 | *
39 | * @param \Illuminate\Http\Request $request
40 | * @param string|null $token
41 | * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
42 | */
43 | public function showResetForm(Request $request, $token = null)
44 | {
45 | return view('auth.passwords.reset')->with(
46 | ['token' => $token]
47 | );
48 | }
49 |
50 | /**
51 | * Reset the given user's password.
52 | *
53 | * @param \App\Http\Requests\Auth\ResetPasswordRequest
54 | * @return \Illuminate\Http\RedirectResponse
55 | */
56 | public function reset(ResetPasswordRequest $request)
57 | {
58 | $params = $request->all();
59 | $reset = $this->authService->resetPassword($params['password'], $params['token']);
60 |
61 | return redirect($this->redirectTo)->with('status', __('passwords.reset'));
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/app/Http/Controllers/Web/ExportController.php:
--------------------------------------------------------------------------------
1 | exportService = $exportService;
18 | }
19 |
20 | public function export(ExportFormRequest $request)
21 | {
22 | // phpcs:ignore Squiz.NamingConventions.ValidVariableName
23 | $fileType = $request->file_type;
24 | $fileName = $this->exportService->makeFilename($fileType);
25 |
26 | $data = $this->exportService->getData($fileType, $request);
27 |
28 | $types = config('common.export.types.' . $fileType . '.mime');
29 |
30 | if ($request->expectsJson()) {
31 | return new ExportResource([
32 | 'fileName' => $fileName,
33 | 'fileMime' => $types,
34 | 'fileDataBase64' => base64_encode($data['encoded']),
35 | 'fileData' => $data['raw'],
36 | ]);
37 | }
38 |
39 | return response()->streamDownload(function () use ($data) {
40 | echo $data;
41 | }, $fileName);
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/app/Http/Controllers/Web/HomeController.php:
--------------------------------------------------------------------------------
1 | middleware('auth');
17 | }
18 |
19 | /**
20 | * Show the application dashboard.
21 | *
22 | * @return \Illuminate\Contracts\Support\Renderable
23 | */
24 | public function index()
25 | {
26 | return view('home');
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/app/Http/Controllers/Web/ImportController.php:
--------------------------------------------------------------------------------
1 | importService = $importService;
18 | }
19 |
20 | public function index()
21 | {
22 | $user = Auth::user();
23 | return view('imports.index', compact('user'));
24 | }
25 |
26 | public function import(ImportFileCsvRequest $request)
27 | {
28 | try {
29 | $this->importService->importFile($request->get('data'));
30 |
31 | return redirect(route('import.create'))->with('message', trans('import.message.success'));
32 | } catch (QueryException $e) {
33 | return redirect()->back()->withErrors([
34 | 'errors' => trans('import.message.import_failed'),
35 | ]);
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/app/Http/Controllers/Web/UserController.php:
--------------------------------------------------------------------------------
1 | prefix = config('web.view_prefix');
14 | }
15 |
16 | protected function render(array $data = [], string $view = null)
17 | {
18 | $view = $view ?: $this->view;
19 | $compacts = array_merge($this->compacts, $data);
20 | return view($this->prefix . $view, $compacts);
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/app/Http/Middleware/Authenticate.php:
--------------------------------------------------------------------------------
1 | expectsJson()) {
18 | return route('login');
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/app/Http/Middleware/CheckForMaintenanceMode.php:
--------------------------------------------------------------------------------
1 | guest()) {
13 | throw UnauthorizedException::notLoggedIn();
14 | }
15 |
16 | if (!auth()->user()->hasPermission($permissions)) {
17 | throw UnauthorizedException::forPermissions($permissions);
18 | }
19 |
20 | return $next($request);
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/app/Http/Middleware/Permission/RoleMiddleware.php:
--------------------------------------------------------------------------------
1 | guest()) {
13 | throw UnauthorizedException::notLoggedIn();
14 | }
15 |
16 | if (!auth()->user()->hasRole($roles)) {
17 | throw UnauthorizedException::forRoles($roles);
18 | }
19 |
20 | return $next($request);
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/app/Http/Middleware/RedirectIfAuthenticated.php:
--------------------------------------------------------------------------------
1 | check()) {
21 | return redirect('/');
22 | }
23 |
24 | return $next($request);
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/app/Http/Middleware/TrimStrings.php:
--------------------------------------------------------------------------------
1 | 'required|email',
28 | ];
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/app/Http/Requests/Auth/LoginRequest.php:
--------------------------------------------------------------------------------
1 | 'required|email|exists:users,email',
28 | 'password' => 'required|min:6',
29 | ];
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/app/Http/Requests/Auth/RegisterRequest.php:
--------------------------------------------------------------------------------
1 | 'required',
28 | 'email' => 'required|email|unique:users,email',
29 | 'password' => 'required|min:6|confirmed',
30 | ];
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/app/Http/Requests/Auth/ResetPasswordRequest.php:
--------------------------------------------------------------------------------
1 | 'required|min:6|confirmed',
29 | 'token' => [
30 | 'required',
31 | 'exists:password_resets,token',
32 | new CheckValidPasswordResetToken,
33 | ],
34 | ];
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/app/Http/Requests/ExportFormRequest.php:
--------------------------------------------------------------------------------
1 | [
29 | 'required',
30 | 'in:' . implode(',', array_keys($cfg['types'])),
31 | ],
32 | 'separation' => Rule::requiredIf(function () use ($cfg) {
33 | // phpcs:ignore Squiz.NamingConventions.ValidVariableName
34 | return $this->file_type === $cfg['types']['csv']['value'];
35 | }),
36 | 'encoding' => [
37 | 'required',
38 | 'in:' . implode(',', array_keys($cfg['encoding'])),
39 | ],
40 | 'export_column' => 'required',
41 | ];
42 | }
43 |
44 | public function messages()
45 | {
46 | return [
47 | 'separation.required' => trans('export.message.separation_required'),
48 | 'encoding.required' => trans('export.message.encoding_required'),
49 | 'encoding.in' => trans('export.message.encoding_in'),
50 | 'file_type.required' => trans('export.message.file_type_required'),
51 | 'file_type.in' => trans('export.message.file_type_in'),
52 | 'export_column.required' => trans('export.message.export_column_required'),
53 | ];
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/app/Http/Requests/ImportFileCsvRequest.php:
--------------------------------------------------------------------------------
1 | [
34 | 'bail',
35 | 'required',
36 | 'max:' . $cfg['max'],
37 | new CheckExtension($cfg['type']),
38 | ],
39 | ];
40 | }
41 |
42 | /**
43 | * Configure the validator instance.
44 | *
45 | * @param \Illuminate\Validation\Validator $validator
46 | * @return void
47 | */
48 |
49 | public function withValidator($validator)
50 | {
51 | if (!$validator->fails()) {
52 | $v = Validator::make(['file' => $this->file], [
53 | 'file' => [new CheckImportFile($this)],
54 | ]);
55 | $v->validate();
56 | }
57 | }
58 |
59 | public function messages()
60 | {
61 | return [
62 | 'file.required' => trans('import.message.file_required'),
63 | 'file.max' => trans('import.message.file_max', ['max' => config('common.import.validation.file.max')]),
64 | ];
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/app/Http/Resources/ApiCollection.php:
--------------------------------------------------------------------------------
1 | message = $message;
17 |
18 | parent::__construct($resource);
19 | }
20 |
21 | public function with($request, object $errors = null)
22 | {
23 | if ($errors === null) {
24 | $errors = new stdClass;
25 | }
26 |
27 | return [
28 | 'message' => $this->message,
29 | 'code' => Response::HTTP_OK,
30 | 'errors' => $errors,
31 | ];
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/app/Http/Resources/ApiResource.php:
--------------------------------------------------------------------------------
1 | message = $message;
19 | $this->errors = $errors;
20 | }
21 |
22 | public function with($request)
23 | {
24 | $this->message = $this->message ?? '';
25 | $this->errors = $this->errors ?? new stdClass;
26 |
27 | return [
28 | 'message' => $this->message,
29 | 'errors' => $this->errors,
30 | 'code' => Response::HTTP_OK,
31 | ];
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/app/Http/Resources/AuthResource.php:
--------------------------------------------------------------------------------
1 | method = $method;
13 | }
14 |
15 | public function toArray($request)
16 | {
17 | return $this->{$this->method}();
18 | }
19 |
20 | public function login()
21 | {
22 | return $this->resource;
23 | }
24 |
25 | public function logout()
26 | {
27 | return [
28 | 'data' => null,
29 | ];
30 | }
31 |
32 | public function register()
33 | {
34 | return $this->resource;
35 | }
36 |
37 | public function sendResetTokenEmail()
38 | {
39 | return [
40 | 'data' => (bool) $this->resource,
41 | ];
42 | }
43 |
44 | public function resetPassword()
45 | {
46 | return [
47 | 'data' => (bool) $this->resource,
48 | ];
49 | }
50 |
51 | public function refreshToken()
52 | {
53 | return $this->resource;
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/app/Http/Resources/ExportResource.php:
--------------------------------------------------------------------------------
1 | method = $method;
12 | parent::__construct($resource, $message);
13 | }
14 |
15 | public function toArray($request)
16 | {
17 | return $this->{$this->method}();
18 | }
19 |
20 | public function export()
21 | {
22 | return [
23 | 'data' => $this->resource,
24 | ];
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/app/Http/Resources/UserResource.php:
--------------------------------------------------------------------------------
1 | method = $method;
12 | parent::__construct($resource, $message);
13 | }
14 |
15 | public function toArray($request)
16 | {
17 | return $this->{$this->method}();
18 | }
19 |
20 | public function show()
21 | {
22 | return [
23 | 'id' => $this->id,
24 | 'name' => $this->name,
25 | 'email' => $this->email,
26 | 'created_at' => $this->created_at->toDateTimeString(), // phpcs:ignore Squiz.NamingConventions.ValidVariableName
27 | 'updated_at' => $this->updated_at->toDateTimeString(), // phpcs:ignore Squiz.NamingConventions.ValidVariableName
28 | ];
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/app/Libraries/ChatApp/ChatAppException.php:
--------------------------------------------------------------------------------
1 | driver($driver);
18 | }
19 | /**
20 | * {@inheritdoc}
21 | */
22 | public function getDefaultDriver()
23 | {
24 | return 'chatwork';
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/app/Libraries/ChatApp/Handlers/Slack.php:
--------------------------------------------------------------------------------
1 | message = $message;
35 |
36 | parent::__construct($client);
37 | }
38 |
39 | public function withEndPoint($endPoint)
40 | {
41 | $this->endPoint = $endPoint;
42 |
43 | return $this;
44 | }
45 |
46 | public function withEnv()
47 | {
48 | $this->endPoint = env('SLACK_HOOK');
49 |
50 | return $this;
51 | }
52 |
53 | /**
54 | * slack message content data.
55 | *
56 | * @return string
57 | */
58 | public function withMessage($message)
59 | {
60 | $this->message->content = $message;
61 |
62 | return $this;
63 | }
64 |
65 | /**
66 | * Send Request to Slack.
67 | *
68 | * @throws RequestFailException
69 | *
70 | * @return array
71 | */
72 | public function dispatch()
73 | {
74 | $this->http->post($this->endPoint, $this->buildJsonPayload(
75 | $this->message
76 | ));
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/app/Libraries/ChatApp/Messages/Chatwork.php:
--------------------------------------------------------------------------------
1 | message = $message;
20 | }
21 |
22 | /**
23 | * Reset message to empty string.
24 | */
25 | public function resetMessage()
26 | {
27 | $this->setMessage('');
28 | }
29 |
30 | /**
31 | * @return string message
32 | */
33 | public function getMessage()
34 | {
35 | return $this->message;
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/app/Libraries/ChatApp/Messages/Slack.php:
--------------------------------------------------------------------------------
1 | message = $message;
22 | }
23 |
24 | /**
25 | * Reset message to empty string.
26 | */
27 | public function resetMessage()
28 | {
29 | $this->setMessage('');
30 | }
31 |
32 | /**
33 | * @return string message
34 | */
35 | public function getMessage()
36 | {
37 | return $this->message;
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/app/Libraries/PermissionRegister.php:
--------------------------------------------------------------------------------
1 | gate = $gate;
22 | }
23 |
24 | /**
25 | * Register the permission check method on the gate.
26 | *
27 | * @return bool
28 | */
29 | public function registerPermissions()
30 | {
31 | $this->gate->before(function (User $user, string $ability) {
32 | try {
33 | if (method_exists($user, 'hasPermission')) {
34 | return $user->hasPermission($ability) ?: null;
35 | }
36 | } catch (PermissionDoesNotExist $e) {
37 | }
38 | });
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/app/Libraries/helpers.php:
--------------------------------------------------------------------------------
1 | $data])->render();
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/app/Listeners/ExceptionThrownListener.php:
--------------------------------------------------------------------------------
1 | handle('chatwork')
31 | ->withEnv()
32 | ->withMessage(generate_message('notification_template.chatwork', $event))
33 | ->dispatch();
34 | resolve('chatapp')
35 | ->handle('slack')
36 | ->withEnv()
37 | ->withMessage(generate_message('notification_template.slack', $event))
38 | ->dispatch();
39 | } catch (Throwable $e) {
40 | Log::error($e);
41 |
42 | throw new ChatAppException();
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/app/Mail/MailForgotPassword.php:
--------------------------------------------------------------------------------
1 | token = $token;
26 | $this->user = $user;
27 | $this->url = $url;
28 | }
29 |
30 | /**
31 | * Build the message.
32 | *
33 | * @return $this
34 | */
35 | public function build()
36 | {
37 | return $this->to($this->user->email)
38 | ->view('emails.mail_forgot_password')
39 | ->with([
40 | 'url' => $this->url ? $this->url : url(sprintf(config('api.auth.reset_password.url'), $this->token)),
41 | 'name' => $this->user->name,
42 | 'timeOut' => config('api.auth.reset_password.token_timeout'),
43 | ]);
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/app/Models/BaseModel.php:
--------------------------------------------------------------------------------
1 | belongsToMany(
18 | Role::class,
19 | 'role_permissions',
20 | 'permission_id',
21 | 'role_id'
22 | );
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/app/Models/Role.php:
--------------------------------------------------------------------------------
1 | belongsToMany(
20 | Permission::class,
21 | 'role_permissions',
22 | 'role_id',
23 | 'permission_id'
24 | );
25 | }
26 |
27 | /**
28 | * A role belongs to some users of the model associated with its guard.
29 | */
30 | public function users(): BelongsToMany
31 | {
32 | return $this->belongsToMany(
33 | User::class,
34 | 'user_roles',
35 | 'role_id',
36 | 'user_id'
37 | );
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/app/Models/User.php:
--------------------------------------------------------------------------------
1 | 'datetime',
42 | ];
43 |
44 | /**
45 | * A user can be applied to roles.
46 | */
47 | public function roles(): BelongsToMany
48 | {
49 | return $this->belongsToMany(
50 | Role::class,
51 | 'user_roles',
52 | 'user_id',
53 | 'role_id'
54 | );
55 | }
56 |
57 | public function setPasswordAttribute($value)
58 | {
59 | $this->attributes['password'] = bcrypt($value);
60 | }
61 |
62 | public function getPermissionsAttribute()
63 | {
64 | if (!$this->relationLoaded('roles') || !$this->roles->first()->relationLoaded('permissions')) {
65 | $this->load('roles.permissions');
66 | }
67 |
68 | return collect($this->roles->pluck('permissions'))->collapse()->unique();
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/app/Policies/AbstractPolicy.php:
--------------------------------------------------------------------------------
1 | deny($message);
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/app/Providers/AppServiceProvider.php:
--------------------------------------------------------------------------------
1 | 'App\Policies\ModelPolicy',
18 | ];
19 |
20 | /**
21 | * Register any authentication / authorization services.
22 | *
23 | * @return void
24 | */
25 | public function boot()
26 | {
27 | $this->registerPolicies();
28 |
29 | Passport::routes();
30 |
31 | Passport::tokensExpireIn(now()->addHours(config('api.auth.token_lifetime_hour.access_token')));
32 |
33 | Passport::refreshTokensExpireIn(now()->addHours(config('api.auth.token_lifetime_hour.refresh_token')));
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/app/Providers/BroadcastServiceProvider.php:
--------------------------------------------------------------------------------
1 | registerManager();
32 | }
33 |
34 | /**
35 | * Register the chatapp manager.
36 | *
37 | * @return void
38 | */
39 | protected function registerManager()
40 | {
41 | $this->app->singleton('chatapp', function ($app) {
42 | return tap(new ChatAppManager($app), function ($manager) {
43 | $this->registerHandlers($manager);
44 | });
45 | });
46 | }
47 |
48 | /**
49 | * Register chatapp handlers.
50 | *
51 | * @param \App\ChatAppNotification\ChatAppManager $manager
52 | * @return void
53 | */
54 | protected function registerHandlers($manager)
55 | {
56 | foreach ([
57 | [
58 | 'chatwork',
59 | Chatwork::class,
60 | ],
61 | [
62 | 'slack',
63 | Slack::class,
64 | ],
65 | ] as $driver) {
66 | $manager->extend($driver[0], function ($app) use ($driver) {
67 | return $this->app->make($driver[1]);
68 | });
69 | }
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/app/Providers/EventServiceProvider.php:
--------------------------------------------------------------------------------
1 | [
21 | SendEmailVerificationNotification::class,
22 | ],
23 | ExceptionThrown::class => [
24 | ExceptionThrownListener::class
25 | ],
26 | ];
27 |
28 | /**
29 | * Register any events for your application.
30 | *
31 | * @return void
32 | */
33 | public function boot()
34 | {
35 | parent::boot();
36 |
37 | //
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/app/Providers/RepositoryServiceProvider.php:
--------------------------------------------------------------------------------
1 | app = $app;
25 | }
26 |
27 | /**
28 | * Register the application services.
29 | *
30 | * @return void
31 | */
32 | public function register()
33 | {
34 | $this->app->bind(UserRepositoryInterface::class, UserRepository::class);
35 | $this->app->bind(PasswordResetTokenRepositoryInterface::class, PasswordResetTokenRepository::class);
36 | $this->app->bind(ImportRepositoryInterface::class, ImportRepository::class);
37 | $this->app->bind(ExportRepositoryInterface::class, ExportRepository::class);
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/app/Providers/RouteServiceProvider.php:
--------------------------------------------------------------------------------
1 | mapApiRoutes();
39 |
40 | $this->mapWebRoutes();
41 |
42 | //
43 | }
44 |
45 | /**
46 | * Define the "web" routes for the application.
47 | *
48 | * These routes all receive session state, CSRF protection, etc.
49 | *
50 | * @return void
51 | */
52 | protected function mapWebRoutes()
53 | {
54 | Route::middleware('web')
55 | ->namespace($this->namespace)
56 | ->group(base_path('routes/web.php'));
57 | }
58 |
59 | /**
60 | * Define the "api" routes for the application.
61 | *
62 | * These routes are typically stateless.
63 | *
64 | * @return void
65 | */
66 | protected function mapApiRoutes()
67 | {
68 | Route::prefix('api')
69 | ->middleware('api')
70 | ->namespace($this->namespace)
71 | ->group(base_path('routes/api.php'));
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/app/Repositories/AppRepositoryInterface.php:
--------------------------------------------------------------------------------
1 | model = $import;
19 | }
20 | /**
21 | * @param array $data
22 | *
23 | * @return bool
24 | */
25 | public function select(array $data)
26 | {
27 | return $this->model->get($data)->toArray();
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/app/Repositories/ExportRepositoryInterface.php:
--------------------------------------------------------------------------------
1 | db = $db;
22 | }
23 |
24 | /**
25 | * @return \Illuminate\Database\Query\Builder
26 | */
27 | protected function query()
28 | {
29 | return $this->db->table('imports');
30 | }
31 |
32 | /**
33 | * @param array $data
34 | *
35 | * @return bool
36 | */
37 | public function insert(array $data)
38 | {
39 | return $this->query()->insert($data);
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/app/Repositories/ImportRepositoryInterface.php:
--------------------------------------------------------------------------------
1 | getObjectToken($token);
18 | $tokenObj->revoked = 1;
19 | $tokenObj->save();
20 |
21 | return $tokenObj;
22 | }
23 |
24 | public function getObjectToken($token)
25 | {
26 | return $this->model
27 | ->where('token', $token)
28 | ->first();
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/app/Repositories/PasswordResetTokenRepositoryInterface.php:
--------------------------------------------------------------------------------
1 | model
17 | ->resetPasswordToken($token)
18 | ->first();
19 | }
20 |
21 | public function getUserByEmail($email)
22 | {
23 | return $this->model
24 | ->where('email', $email)
25 | ->first();
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/app/Repositories/UserRepositoryInterface.php:
--------------------------------------------------------------------------------
1 | parameters = $parameters;
22 | }
23 |
24 | /**
25 | * Determine if the validation rule passes.
26 | *
27 | * @param string $attribute
28 | * @param mixed $value
29 | * @return bool
30 | */
31 | public function passes($attribute, $value)
32 | {
33 | $extension = $value->getClientOriginalExtension();
34 | return in_array($extension, $this->parameters);
35 | }
36 |
37 | /**
38 | * Get the validation error message.
39 | *
40 | * @return string
41 | */
42 | public function message()
43 | {
44 | return trans('import.message.file_mimes', ['format' => implode(', ', $this->parameters)]);
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/app/Rules/CheckValidPasswordResetToken.php:
--------------------------------------------------------------------------------
1 | getObjectToken($value);
30 | return !$token || !$token->revoked;
31 | }
32 |
33 | /**
34 | * Get the validation error message.
35 | *
36 | * @return string
37 | */
38 | public function message()
39 | {
40 | return __('passwords.token');
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/app/Services/AppService.php:
--------------------------------------------------------------------------------
1 | repository = $repository;
14 | }
15 |
16 | public function getModel()
17 | {
18 | return $this->repository->getModel();
19 | }
20 |
21 | public function fetchAll(array $columns = ['*'])
22 | {
23 | return $this->repository->fetchAll($columns);
24 | }
25 |
26 | public function fetchList()
27 | {
28 | return $this->repository->fetchList();
29 | }
30 |
31 | public function paginateList($params)
32 | {
33 | $page = isset($params['page']) ? $params['page'] : config('common.page_default');
34 |
35 | return $this->repository->paginateList($page);
36 | }
37 |
38 | public function findById($id, array $columns = ['*'])
39 | {
40 | return $this->repository->findById($id, $columns);
41 | }
42 |
43 | public function store(array $data)
44 | {
45 | return $this->repository->store($data);
46 | }
47 |
48 | public function update($id, array $data)
49 | {
50 | return $this->repository->update($id, $data);
51 | }
52 |
53 | public function delete(array $data)
54 | {
55 | return $this->repository->delete($data);
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/app/Services/ImportService.php:
--------------------------------------------------------------------------------
1 | repoImport = $repoImport;
16 | }
17 |
18 | public function importFile($importData)
19 | {
20 | return $this->repoImport->insert($importData);
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/app/Services/UserService.php:
--------------------------------------------------------------------------------
1 | userRepository = $userRepository;
17 | }
18 |
19 | public function paginateList($params)
20 | {
21 | $params = filter($params, ['keyword']);
22 | $page = isset($params['page']) ? $params['page'] : config('common.page_default');
23 | $keyword = isset($params['keyword']) ? $params['keyword'] : '';
24 |
25 | return $this->userRepository->paginateList($page, ['*'], $keyword);
26 | }
27 |
28 | public function deleteUserById(int $id)
29 | {
30 | return $this->userRepository->delete($id);
31 | }
32 |
33 | public function getUserByEmail(string $email)
34 | {
35 | return $this->userRepository->getUserByEmail($email);
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/artisan:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env php
2 | make(Illuminate\Contracts\Console\Kernel::class);
34 |
35 | $status = $kernel->handle(
36 | $input = new Symfony\Component\Console\Input\ArgvInput,
37 | new Symfony\Component\Console\Output\ConsoleOutput
38 | );
39 |
40 | /*
41 | |--------------------------------------------------------------------------
42 | | Shutdown The Application
43 | |--------------------------------------------------------------------------
44 | |
45 | | Once Artisan has finished running, we will fire off the shutdown events
46 | | so that any final work may be done by the application before we shut
47 | | down the process. This is the last thing to happen to the request.
48 | |
49 | */
50 |
51 | $kernel->terminate($input, $status);
52 |
53 | exit($status);
54 |
--------------------------------------------------------------------------------
/bootstrap/app.php:
--------------------------------------------------------------------------------
1 | singleton(
30 | Illuminate\Contracts\Http\Kernel::class,
31 | App\Http\Kernel::class
32 | );
33 |
34 | $app->singleton(
35 | Illuminate\Contracts\Console\Kernel::class,
36 | App\Console\Kernel::class
37 | );
38 |
39 | $app->singleton(
40 | Illuminate\Contracts\Debug\ExceptionHandler::class,
41 | App\Exceptions\Handler::class
42 | );
43 |
44 | /*
45 | |--------------------------------------------------------------------------
46 | | Return The Application
47 | |--------------------------------------------------------------------------
48 | |
49 | | This script returns the application instance. The instance is given to
50 | | the calling script so we can separate the building of the instances
51 | | from the actual running of the application and sending responses.
52 | |
53 | */
54 |
55 | return $app;
56 |
--------------------------------------------------------------------------------
/bootstrap/cache/.gitignore:
--------------------------------------------------------------------------------
1 | *
2 | !.gitignore
3 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "laravel/laravel",
3 | "type": "project",
4 | "description": "The Laravel Framework.",
5 | "keywords": [
6 | "framework",
7 | "laravel"
8 | ],
9 | "license": "MIT",
10 | "require": {
11 | "php": "^7.1.3",
12 | "fideloper/proxy": "^4.0",
13 | "guzzlehttp/guzzle": "^6.3",
14 | "laravel/framework": "5.8.*",
15 | "laravel/passport": "^7.3",
16 | "laravel/slack-notification-channel": "^2.0",
17 | "laravel/tinker": "^1.0",
18 | "lord/laroute": "^2.4",
19 | "predis/predis": "^1.1",
20 | "squizlabs/php_codesniffer": "^3.4"
21 | },
22 | "require-dev": {
23 | "beyondcode/laravel-dump-server": "^1.0",
24 | "filp/whoops": "^2.0",
25 | "fzaninotto/faker": "^1.4",
26 | "mockery/mockery": "^1.0",
27 | "nunomaduro/collision": "^2.0",
28 | "phpunit/phpunit": "^7.5"
29 | },
30 | "config": {
31 | "optimize-autoloader": true,
32 | "preferred-install": "dist",
33 | "sort-packages": true
34 | },
35 | "extra": {
36 | "laravel": {
37 | "dont-discover": []
38 | }
39 | },
40 | "autoload": {
41 | "psr-4": {
42 | "App\\": "app/"
43 | },
44 | "files": [
45 | "app/Libraries/helpers.php"
46 | ],
47 | "classmap": [
48 | "database/seeds",
49 | "database/factories"
50 | ]
51 | },
52 | "autoload-dev": {
53 | "psr-4": {
54 | "Tests\\": "tests/"
55 | }
56 | },
57 | "minimum-stability": "dev",
58 | "prefer-stable": true,
59 | "scripts": {
60 | "post-autoload-dump": [
61 | "Illuminate\\Foundation\\ComposerScripts::postAutoloadDump",
62 | "@php artisan package:discover --ansi"
63 | ],
64 | "post-root-package-install": [
65 | "@php -r \"file_exists('.env') || copy('.env.example', '.env');\""
66 | ],
67 | "post-create-project-cmd": [
68 | "@php artisan key:generate --ansi"
69 | ]
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/config/api.php:
--------------------------------------------------------------------------------
1 | 'v1',
5 | 'prefix' => 'api',
6 | 'auth' => [
7 | 'reset_password' => [
8 | 'token_timeout' => 60,
9 | 'url' => 'reset-password/%s',
10 | ],
11 | 'token_lifetime_hour' => [
12 | 'access_token' => 1,
13 | 'refresh_token' => 48,
14 | ],
15 | ],
16 | ];
17 |
--------------------------------------------------------------------------------
/config/broadcasting.php:
--------------------------------------------------------------------------------
1 | env('BROADCAST_DRIVER', 'null'),
19 |
20 | /*
21 | |--------------------------------------------------------------------------
22 | | Broadcast Connections
23 | |--------------------------------------------------------------------------
24 | |
25 | | Here you may define all of the broadcast connections that will be used
26 | | to broadcast events to other systems or over websockets. Samples of
27 | | each available type of connection are provided inside this array.
28 | |
29 | */
30 |
31 | 'connections' => [
32 |
33 | 'pusher' => [
34 | 'driver' => 'pusher',
35 | 'key' => env('PUSHER_APP_KEY'),
36 | 'secret' => env('PUSHER_APP_SECRET'),
37 | 'app_id' => env('PUSHER_APP_ID'),
38 | 'options' => [
39 | 'cluster' => env('PUSHER_APP_CLUSTER'),
40 | 'encrypted' => true,
41 | ],
42 | ],
43 |
44 | 'redis' => [
45 | 'driver' => 'redis',
46 | 'connection' => 'default',
47 | ],
48 |
49 | 'log' => [
50 | 'driver' => 'log',
51 | ],
52 |
53 | 'null' => [
54 | 'driver' => 'null',
55 | ],
56 |
57 | ],
58 |
59 | ];
60 |
--------------------------------------------------------------------------------
/config/common.php:
--------------------------------------------------------------------------------
1 | 12,
5 | 'page_default' => 1,
6 | 'import' => [
7 | 'validation' => [
8 | 'name' => [
9 | 'max' => 25,
10 | ],
11 | 'file' => [
12 | 'header' => [
13 | 'id' => 'import.header_text.id',
14 | 'name' => 'import.header_text.name',
15 | 'created_at' => 'import.header_text.created_at',
16 | ],
17 | 'type' => ['csv','tsv','xls','xlsx'],
18 | 'max' => 4096,
19 | ],
20 | ],
21 | ],
22 | 'export' => [
23 | 'file_name' => 'Export-%s',
24 | 'types' => [
25 | 'xlsx' => [
26 | 'label' => 'export.file_type.excel',
27 | 'value' => 'xlsx',
28 | 'mime' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
29 | ],
30 | 'csv' => [
31 | 'label' => 'export.file_type.csv',
32 | 'value' => 'csv',
33 | 'mime' => 'text/csv',
34 | 'separation' => [
35 | 'tab' => [
36 | 'label' => 'export.separate_char.tab',
37 | 'value' => '\t',
38 | ],
39 | 'comma' => [
40 | 'label' => 'export.separate_char.comma',
41 | 'value' => ',',
42 | ],
43 | 'semi_colon' => [
44 | 'label' => 'export.separate_char.semi_colon',
45 | 'value' => ';',
46 | ],
47 | ],
48 | ],
49 | ],
50 | 'export_column' => [
51 | 'id' => 'export.export_column.id',
52 | 'name' => 'export.export_column.name',
53 | 'created_at' => 'export.export_column.created_at',
54 | 'updated_at' => 'export.export_column.updated_at',
55 | ],
56 | 'encoding' => [
57 | 'utf8' => 'UTF-8',
58 | 'shiftjis' => 'Shift-JIS',
59 | 'eucjp' => 'EUC-JP',
60 | ],
61 | ],
62 | ];
63 |
--------------------------------------------------------------------------------
/config/hashing.php:
--------------------------------------------------------------------------------
1 | 'bcrypt',
19 |
20 | /*
21 | |--------------------------------------------------------------------------
22 | | Bcrypt Options
23 | |--------------------------------------------------------------------------
24 | |
25 | | Here you may specify the configuration options that should be used when
26 | | passwords are hashed using the Bcrypt algorithm. This will allow you
27 | | to control the amount of time it takes to hash the given password.
28 | |
29 | */
30 |
31 | 'bcrypt' => [
32 | 'rounds' => env('BCRYPT_ROUNDS', 10),
33 | ],
34 |
35 | /*
36 | |--------------------------------------------------------------------------
37 | | Argon Options
38 | |--------------------------------------------------------------------------
39 | |
40 | | Here you may specify the configuration options that should be used when
41 | | passwords are hashed using the Argon algorithm. These will allow you
42 | | to control the amount of time it takes to hash the given password.
43 | |
44 | */
45 |
46 | 'argon' => [
47 | 'memory' => 1024,
48 | 'threads' => 2,
49 | 'time' => 2,
50 | ],
51 |
52 | ];
53 |
--------------------------------------------------------------------------------
/config/laroute.php:
--------------------------------------------------------------------------------
1 | 'resources/js',
9 |
10 | /*
11 | * The destination filename for the javascript file.
12 | */
13 | 'filename' => 'endpoint',
14 |
15 | /*
16 | * The namespace for the helper functions. By default this will bind them to
17 | * `window.laroute`.
18 | */
19 | 'namespace' => 'endpoint',
20 |
21 | /*
22 | * Generate absolute URLs
23 | *
24 | * Set the Application URL in config/app.php
25 | */
26 | 'absolute' => false,
27 |
28 | /*
29 | * The Filter Method
30 | *
31 | * 'all' => All routes except "'laroute' => false"
32 | * 'only' => Only "'laroute' => true" routes
33 | * 'force' => All routes, ignored "laroute" route parameter
34 | */
35 | 'filter' => 'all',
36 |
37 | /*
38 | * Controller Namespace
39 | *
40 | * Set here your controller namespace (see RouteServiceProvider -> $namespace) for cleaner action calls
41 | * e.g. 'App\Http\Controllers'
42 | */
43 | 'action_namespace' => 'Api',
44 |
45 | /*
46 | * The path to the template `laroute.js` file. This is the file that contains
47 | * the ported helper Laravel url/route functions and the route data to go
48 | * with them.
49 | */
50 | 'template' => 'vendor/lord/laroute/src/templates/laroute.js',
51 |
52 | /*
53 | * Appends a prefix to URLs. By default the prefix is an empty string.
54 | *
55 | */
56 | 'prefix' => '',
57 |
58 | ];
59 |
--------------------------------------------------------------------------------
/config/permission.php:
--------------------------------------------------------------------------------
1 | [
5 | 'admin' => 'admin',
6 | ],
7 |
8 | 'permission' => [
9 | 'user' => [
10 | 'view' => 'view-user',
11 | 'create' => 'create-user',
12 | 'update' => 'update-user',
13 | 'delete' => 'delete-user',
14 | ],
15 | ],
16 |
17 | 'role_permission' => [
18 | 'admin' => [
19 | 'user.view',
20 | 'user.create',
21 | 'user.update',
22 | 'user.delete',
23 | ],
24 | ],
25 | ];
26 |
--------------------------------------------------------------------------------
/config/services.php:
--------------------------------------------------------------------------------
1 | [
18 | 'domain' => env('MAILGUN_DOMAIN'),
19 | 'secret' => env('MAILGUN_SECRET'),
20 | 'endpoint' => env('MAILGUN_ENDPOINT', 'api.mailgun.net'),
21 | ],
22 |
23 | 'postmark' => [
24 | 'token' => env('POSTMARK_TOKEN'),
25 | ],
26 |
27 | 'ses' => [
28 | 'key' => env('AWS_ACCESS_KEY_ID'),
29 | 'secret' => env('AWS_SECRET_ACCESS_KEY'),
30 | 'region' => env('AWS_DEFAULT_REGION', 'us-east-1'),
31 | ],
32 |
33 | 'sparkpost' => [
34 | 'secret' => env('SPARKPOST_SECRET'),
35 | ],
36 |
37 | 'stripe' => [
38 | 'model' => App\User::class,
39 | 'key' => env('STRIPE_KEY'),
40 | 'secret' => env('STRIPE_SECRET'),
41 | 'webhook' => [
42 | 'secret' => env('STRIPE_WEBHOOK_SECRET'),
43 | 'tolerance' => env('STRIPE_WEBHOOK_TOLERANCE', 300),
44 | ],
45 | ],
46 |
47 | ];
48 |
--------------------------------------------------------------------------------
/config/view.php:
--------------------------------------------------------------------------------
1 | [
17 | resource_path('views'),
18 | ],
19 |
20 | /*
21 | |--------------------------------------------------------------------------
22 | | Compiled View Path
23 | |--------------------------------------------------------------------------
24 | |
25 | | This option determines where all the compiled Blade templates will be
26 | | stored for your application. Typically, this is within the storage
27 | | directory. However, as usual, you are free to change this value.
28 | |
29 | */
30 |
31 | 'compiled' => env(
32 | 'VIEW_COMPILED_PATH',
33 | realpath(storage_path('framework/views'))
34 | ),
35 |
36 | ];
37 |
--------------------------------------------------------------------------------
/config/web.php:
--------------------------------------------------------------------------------
1 | 'web',
5 | ];
6 |
--------------------------------------------------------------------------------
/database/.gitignore:
--------------------------------------------------------------------------------
1 | *.sqlite
2 |
--------------------------------------------------------------------------------
/database/factories/ImportFactory.php:
--------------------------------------------------------------------------------
1 | define(Import::class, function (Faker $faker) {
19 | return [
20 | 'name' => $faker->name,
21 | ];
22 | });
23 |
--------------------------------------------------------------------------------
/database/factories/PermissionFactory.php:
--------------------------------------------------------------------------------
1 | define(Permission::class, function (Faker $faker) {
9 | return [
10 | 'name' => $faker->name,
11 | ];
12 | });
13 |
--------------------------------------------------------------------------------
/database/factories/RoleFactory.php:
--------------------------------------------------------------------------------
1 | define(Role::class, function (Faker $faker) {
10 | return [
11 | 'name' => $faker->name,
12 | ];
13 | });
14 |
--------------------------------------------------------------------------------
/database/factories/UserFactory.php:
--------------------------------------------------------------------------------
1 | define(User::class, function (Faker $faker) {
19 | return [
20 | 'name' => $faker->name,
21 | 'email' => $faker->unique()->safeEmail,
22 | 'email_verified_at' => now(),
23 | 'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password
24 | 'remember_token' => Str::random(10),
25 | ];
26 | });
27 |
--------------------------------------------------------------------------------
/database/migrations/2014_10_12_000000_create_users_table.php:
--------------------------------------------------------------------------------
1 | bigIncrements('id');
18 | $table->string('name');
19 | $table->string('email')->unique();
20 | $table->timestamp('email_verified_at')->nullable();
21 | $table->string('password');
22 | $table->rememberToken();
23 | $table->timestamps();
24 | });
25 | }
26 |
27 | /**
28 | * Reverse the migrations.
29 | *
30 | * @return void
31 | */
32 | public function down()
33 | {
34 | Schema::dropIfExists('users');
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/database/migrations/2014_10_12_100000_create_password_resets_table.php:
--------------------------------------------------------------------------------
1 | bigIncrements('id');
18 | $table->string('email')->index();
19 | $table->string('token');
20 | $table->tinyInteger('revoked')->default(0);
21 | $table->timestamps();
22 | });
23 | }
24 |
25 | /**
26 | * Reverse the migrations.
27 | *
28 | * @return void
29 | */
30 | public function down()
31 | {
32 | Schema::dropIfExists('password_resets');
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/database/migrations/2019_08_19_102724_create_imports_table.php:
--------------------------------------------------------------------------------
1 | increments('id');
18 | $table->string('name');
19 | $table->timestamps();
20 | });
21 | }
22 |
23 | /**
24 | * Reverse the migrations.
25 | *
26 | * @return void
27 | */
28 | public function down()
29 | {
30 | Schema::dropIfExists('imports');
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/database/seeds/DatabaseSeeder.php:
--------------------------------------------------------------------------------
1 | call(UserTableSeeder::class);
15 | $this->call(RolePermissionSeeder::class);
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/database/seeds/RolePermissionSeeder.php:
--------------------------------------------------------------------------------
1 | $v];
22 | }
23 | }
24 | foreach (config('permission.role') as $key => $value) {
25 | $role[] = ['name' => $value];
26 | }
27 |
28 | Role::insert($role);
29 | Permission::insert($permission);
30 |
31 | foreach (config('permission.role_permission') as $key => $value) {
32 | $role = Role::where('name', $key)->first();
33 | foreach ($value as $v) {
34 | $role->assignPermission(config('permission.permission.' . $v));
35 | }
36 | }
37 |
38 | $users = User::get();
39 | foreach ($users as $key => $user) {
40 | $user->assignRole(Role::all()->random());
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/database/seeds/UserTableSeeder.php:
--------------------------------------------------------------------------------
1 | 'Admin',
18 | 'email' => 'admin@example.com',
19 | 'password' => bcrypt(123456),
20 | ],
21 | [
22 | 'name' => 'Member',
23 | 'email' => 'member@example.com',
24 | 'password' => bcrypt(123456),
25 | ],
26 | ];
27 | User::insert($dump);
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/mergeManifest.js:
--------------------------------------------------------------------------------
1 | let mix = require('laravel-mix');
2 | let ManifestPlugin = require('laravel-mix/src/webpackPlugins/ManifestPlugin');
3 | let merge = require('lodash').merge;
4 |
5 | /*
6 | * Because we compile css and js file in 2 seperated command,
7 | * so to prevent mix-manifest.json is overwrited by follow occured command, this function help to merge it all.
8 | */
9 |
10 | module.exports = (config) => {
11 | config.plugins.forEach((plugin, index) => {
12 | if (plugin instanceof ManifestPlugin) {
13 | config.plugins.splice(index, 1);
14 | }
15 | });
16 |
17 | config.plugins.push(new class {
18 | apply(compiler) {
19 |
20 | compiler.plugin('emit', (curCompiler, callback) => {
21 | let stats = curCompiler.getStats().toJson();
22 |
23 | try {
24 | Mix.manifest.manifest = merge(Mix.manifest.read(), Mix.manifest.manifest);
25 | } catch (e) {
26 |
27 | }
28 |
29 | Mix.manifest.transform(stats).refresh();
30 | callback();
31 | });
32 | }
33 | })
34 | };
35 |
--------------------------------------------------------------------------------
/phpunit.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
13 | ./tests/Unit
14 |
15 |
16 |
17 | ./tests/Feature
18 |
19 |
20 |
21 |
22 | ./app
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/public/.htaccess:
--------------------------------------------------------------------------------
1 |
2 |
3 | Options -MultiViews -Indexes
4 |
5 |
6 | RewriteEngine On
7 |
8 | # Handle Authorization Header
9 | RewriteCond %{HTTP:Authorization} .
10 | RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
11 |
12 | # Redirect Trailing Slashes If Not A Folder...
13 | RewriteCond %{REQUEST_FILENAME} !-d
14 | RewriteCond %{REQUEST_URI} (.+)/$
15 | RewriteRule ^ %1 [L,R=301]
16 |
17 | # Handle Front Controller...
18 | RewriteCond %{REQUEST_FILENAME} !-d
19 | RewriteCond %{REQUEST_FILENAME} !-f
20 | RewriteRule ^ index.php [L]
21 |
22 |
--------------------------------------------------------------------------------
/public/css/.gitignore:
--------------------------------------------------------------------------------
1 | *
2 | !.gitignore
3 |
--------------------------------------------------------------------------------
/public/export.csv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/euclid1990/laravel/19a5b008c5649aef143b988c233c4fcfbb88557f/public/export.csv
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/euclid1990/laravel/19a5b008c5649aef143b988c233c4fcfbb88557f/public/favicon.ico
--------------------------------------------------------------------------------
/public/index.php:
--------------------------------------------------------------------------------
1 |
8 | */
9 |
10 | define('LARAVEL_START', microtime(true));
11 |
12 | /*
13 | |--------------------------------------------------------------------------
14 | | Register The Auto Loader
15 | |--------------------------------------------------------------------------
16 | |
17 | | Composer provides a convenient, automatically generated class loader for
18 | | our application. We just need to utilize it! We'll simply require it
19 | | into the script here so that we don't have to worry about manual
20 | | loading any of our classes later on. It feels great to relax.
21 | |
22 | */
23 |
24 | require __DIR__.'/../vendor/autoload.php';
25 |
26 | /*
27 | |--------------------------------------------------------------------------
28 | | Turn On The Lights
29 | |--------------------------------------------------------------------------
30 | |
31 | | We need to illuminate PHP development, so let us turn on the lights.
32 | | This bootstraps the framework and gets it ready for use, then it
33 | | will load up this application so that we can run it and send
34 | | the responses back to the browser and delight our users.
35 | |
36 | */
37 |
38 | $app = require_once __DIR__.'/../bootstrap/app.php';
39 |
40 | /*
41 | |--------------------------------------------------------------------------
42 | | Run The Application
43 | |--------------------------------------------------------------------------
44 | |
45 | | Once we have the application, we can handle the incoming request
46 | | through the kernel, and send the associated response back to
47 | | the client's browser allowing them to enjoy the creative
48 | | and wonderful application we have prepared for them.
49 | |
50 | */
51 |
52 | $kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);
53 |
54 | $response = $kernel->handle(
55 | $request = Illuminate\Http\Request::capture()
56 | );
57 |
58 | $response->send();
59 |
60 | $kernel->terminate($request, $response);
61 |
--------------------------------------------------------------------------------
/public/js/.gitignore:
--------------------------------------------------------------------------------
1 | *
2 | !.gitignore
3 |
--------------------------------------------------------------------------------
/public/robots.txt:
--------------------------------------------------------------------------------
1 | User-agent: *
2 | Disallow:
3 |
--------------------------------------------------------------------------------
/public/web.config:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/resources/js/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
18 |
19 |
28 |
--------------------------------------------------------------------------------
/resources/js/app.js:
--------------------------------------------------------------------------------
1 |
2 | /**
3 | * First we will load all of this project's JavaScript dependencies which
4 | * includes Vue and other libraries. It is a great starting point when
5 | * building robust, powerful web applications using Vue and Laravel.
6 | */
7 | import App from '@/App.vue'
8 | import router from '@/router'
9 |
10 | import { i18n } from '@/utils'
11 | import store from '@/store'
12 |
13 | import BootstrapVue from 'bootstrap-vue'
14 | import VeeValidate from 'vee-validate'
15 | import VueSweetalert2 from 'vue-sweetalert2'
16 | import Fragment from 'vue-fragment'
17 | import Vue from 'vue'
18 |
19 | window.endpoint = require('./endpoint')
20 |
21 | Vue.use(Fragment.Plugin)
22 | Vue.use(BootstrapVue)
23 | Vue.use(VueSweetalert2)
24 | Vue.use(VeeValidate)
25 |
26 | new Vue({
27 | render: h => h(App),
28 | i18n,
29 | router,
30 | store
31 | }).$mount('#app')
32 |
--------------------------------------------------------------------------------
/resources/js/constants/index.js:
--------------------------------------------------------------------------------
1 | export const ACCESS_TOKEN = 'access_token'
2 | export const DEFAULT_LANGUAGE = 'en'
3 |
--------------------------------------------------------------------------------
/resources/js/langs/en.js:
--------------------------------------------------------------------------------
1 | export default {
2 | en: {
3 | error: {
4 | token_expired: {
5 | title: 'Access token expired',
6 | text: 'Your access token had been expired'
7 | },
8 | server: {
9 | 500: 'Internal server error',
10 | text: 'Something wrong with server'
11 | },
12 | forbidden: {
13 | 403: 'Client Error',
14 | text: 'You do not have permission to access on this serve'
15 | },
16 | not_found: {
17 | 404: 'Client Error',
18 | text: 'The requested resource could not be found'
19 | },
20 | unknown: {
21 | title: 'Unknown error',
22 | text: 'Request error'
23 | }
24 | },
25 | button: {
26 | swal: {
27 | ok: 'Ok !',
28 | cancel: 'Cancel !'
29 | }
30 | },
31 | export: {
32 | export_column: {
33 | id: 'ID',
34 | name: 'Name',
35 | created_at: 'Created At',
36 | updated_at: 'Updated At'
37 | },
38 | file_type: {
39 | excel: 'excel',
40 | csv: 'csv'
41 | },
42 | separate_char: {
43 | tab: 'Tab',
44 | comma: 'Comma',
45 | semi_colon: 'Semi Colon'
46 | },
47 | title: 'Export table imports to csv file',
48 | choose_file_label: 'Choose an File type',
49 | choose_separate_label: 'Choose a separate char',
50 | choose_encoding: 'Choose an type encoding',
51 | choose_field: 'Choose field',
52 | export: 'Export',
53 | file_type_validate: 'File type',
54 | separate_char_validate: 'Separate char',
55 | encoding_type_validate: 'Encoding type',
56 | allow_column_validate: 'Export column'
57 | }
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/resources/js/langs/vi.js:
--------------------------------------------------------------------------------
1 | export default {
2 | vi: {
3 | error: {
4 | token_expired: {
5 | title: 'Access token expired',
6 | text: 'Your access token had been expired'
7 | },
8 | server: 'Something wrong with server'
9 | },
10 | button: {
11 | swal: {
12 | ok: 'Ok !',
13 | cancel: 'Cancel !'
14 | }
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/resources/js/mixins/RedirectIfAuthenticated.js:
--------------------------------------------------------------------------------
1 | import { mapGetters } from 'vuex'
2 |
3 | export default {
4 | computed: {
5 | ...mapGetters({
6 | check: 'auth/check'
7 | })
8 | },
9 |
10 | methods: {
11 | __protectRoute() {
12 | if (this.check) {
13 | this.__redirect()
14 | }
15 | },
16 |
17 | __redirect() {
18 | const redirect = {
19 | path: this.$router.resolve({ name: 'dashboard' }).href
20 | }
21 |
22 | this.$router.push(redirect)
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/resources/js/pages/Auth/LoginPage.vue:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
29 |
30 |
31 |
33 |
--------------------------------------------------------------------------------
/resources/js/pages/Auth/RegisterPage.vue:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
29 |
30 |
31 |
33 |
--------------------------------------------------------------------------------
/resources/js/pages/DashboardPage.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |

8 |
9 |
13 |
14 |
15 |
16 |
23 |
24 |
25 |
35 |
--------------------------------------------------------------------------------
/resources/js/pages/Layout/AppLayout.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
15 |
16 |
17 |
19 |
--------------------------------------------------------------------------------
/resources/js/router/middlewares/auth.js:
--------------------------------------------------------------------------------
1 | export default function auth({ next, router }) {
2 | if (!localStorage.getItem('access_token')) {
3 | return router.push({ name: 'login' })
4 | }
5 |
6 | return next()
7 | }
8 |
--------------------------------------------------------------------------------
/resources/js/store/auth/mutation-types.js:
--------------------------------------------------------------------------------
1 | // auth.js
2 | export const LOGOUT = 'LOGOUT'
3 | export const LOGIN_SUCCESS = 'SAVE_TOKEN'
4 | export const LOGIN_FAILURE = 'FETCH_USER'
5 | export const FETCH_USER = 'UPDATE_USER'
6 | export const UPDATE_TOKEN = 'UPDATE_TOKEN'
7 |
--------------------------------------------------------------------------------
/resources/js/store/index.js:
--------------------------------------------------------------------------------
1 | import Vuex from 'vuex'
2 | import Vue from 'vue'
3 | import * as auth from '@/store/auth'
4 |
5 | Vue.use(Vuex)
6 |
7 | const store = new Vuex.Store({
8 | modules: {
9 | auth
10 | }
11 | })
12 |
13 | export default store
14 |
--------------------------------------------------------------------------------
/resources/js/utils/env.js:
--------------------------------------------------------------------------------
1 | export default function env(e, d = '') {
2 | if (typeof process.env[e] === 'undefined' || process.env[e] === '') return d
3 |
4 | return process.env[e]
5 | }
6 |
--------------------------------------------------------------------------------
/resources/js/utils/i18n/formatter.js:
--------------------------------------------------------------------------------
1 | import MessageFormat from 'messageformat'
2 | import { DEFAULT_LANGUAGE } from '@/constants'
3 |
4 | export default class CustomFormatter {
5 | constructor(options = {}) {
6 | this._locale = options.locale || DEFAULT_LANGUAGE
7 | this._formatter = new MessageFormat(this._locale)
8 | this._caches = Object.create(null)
9 | }
10 |
11 | interpolate(message, values) {
12 | let fn = this._caches[message]
13 | if (!fn) {
14 | fn = this._formatter.compile(message, this._locale)
15 | this._caches[message] = fn
16 | }
17 | return [fn(values)]
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/resources/js/utils/i18n/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import VueI18n from 'vue-i18n'
3 | import Formatter from '@/utils/i18n/formatter'
4 | import axios from 'axios'
5 |
6 | Vue.use(VueI18n)
7 |
8 | const messages = require(`@/langs/${window.config.lang}`).default
9 |
10 | const loadedLanguages = []
11 | const locale = window.config.lang
12 | const formatter = new Formatter({ locale })
13 |
14 | const i18n = new VueI18n({
15 | locale,
16 | formatter,
17 | messages,
18 | silentTranslationWarn: false
19 | })
20 |
21 | loadedLanguages.push(locale)
22 |
23 | function setI18nLanguage(lang) {
24 | i18n.locale = lang
25 | axios.defaults.headers.common['Accept-Language'] = lang
26 | document.querySelector('html').setAttribute('lang', lang)
27 |
28 | return lang
29 | }
30 |
31 | const $t = i18n.tc.bind(i18n)
32 |
33 | function loadLanguageAsync(lang) {
34 | if (i18n.locale !== lang) {
35 | if (!loadedLanguages.includes(lang)) {
36 | return import(/* webpackChunkName: "lang-[request]" */ `@/langs/${lang}`).then(msgs => {
37 | i18n.setLocaleMessage(lang, msgs.default)
38 | loadedLanguages.push(lang)
39 |
40 | return setI18nLanguage(lang)
41 | })
42 | }
43 |
44 | return Promise.resolve(setI18nLanguage(lang))
45 | }
46 |
47 | return Promise.resolve(lang)
48 | }
49 |
50 | export {
51 | i18n,
52 | $t,
53 | loadLanguageAsync
54 | }
55 |
--------------------------------------------------------------------------------
/resources/js/utils/index.js:
--------------------------------------------------------------------------------
1 | import '@/utils/api'
2 | import { i18n } from './i18n'
3 |
4 | export {
5 | i18n
6 | }
7 |
--------------------------------------------------------------------------------
/resources/js/utils/route.js:
--------------------------------------------------------------------------------
1 | import env from '@/utils/env'
2 |
3 | const URL_PREFIX = '/' + env('MIX_API_PREFIX', 'api') + '/' + env('MIX_API_VERSION', 'v1') + '/'
4 |
5 | const ROUTE_PREFIX = env('MIX_API_PREFIX', 'api') + '.' + env('MIX_API_VERSION', 'v1') + '.'
6 |
7 | const route = (name, parameters = {}) => {
8 | return window.endpoint.route(ROUTE_PREFIX + name, parameters)
9 | }
10 |
11 | const url = (url, parameters = {}) => {
12 | return window.endpoint.url(URL_PREFIX + url, parameters)
13 | }
14 |
15 | export {
16 | route,
17 | url
18 | }
19 |
--------------------------------------------------------------------------------
/resources/js/utils/swal.js:
--------------------------------------------------------------------------------
1 | import { $t } from '@/utils/i18n'
2 | import Sweetalert2 from 'sweetalert2'
3 |
4 | const base = {
5 | reverseButtons: true,
6 | confirmButtonText: $t('button.swal.ok'),
7 | cancelButtonText: $t('button.swal.cancel')
8 | }
9 |
10 | const baseconfig = {
11 | warning: {
12 | ...base,
13 | type: 'warning'
14 |
15 | },
16 | error: {
17 | ...base,
18 | type: 'error'
19 |
20 | },
21 | success: {
22 | ...base,
23 | type: 'success'
24 | }
25 | }
26 |
27 | export default function swal(type, config) {
28 | return Sweetalert2.fire({
29 | ...baseconfig[type],
30 | ...config
31 | })
32 | }
33 |
--------------------------------------------------------------------------------
/resources/lang/en/auth.php:
--------------------------------------------------------------------------------
1 | 'These credentials do not match our records.',
17 | 'throttle' => 'Too many login attempts. Please try again in :seconds seconds.',
18 | 'login' => 'Login',
19 | 'logout' => 'Logout success.',
20 | 'register' => 'Register',
21 |
22 | 'email_address' => 'Email address',
23 | 'reset_password' => 'Reset password',
24 | 'name' => 'Name',
25 | 'password' => 'Password',
26 | 'confirm_password' => 'Confirm Password',
27 | 'remember_me' => 'Remember me',
28 | 'forgot_your_password' => 'Forgot your password?',
29 | 'send_password_reset_link' => 'Send password reset link',
30 |
31 | 'verify_link_notice' => 'Before proceeding, please check your email for a verification link.',
32 | 'verify_link_not_receive' => 'If you did not receive the email',
33 | 'verify_link_resend' => 'click here to request another',
34 | 'verify_link_success' => 'A fresh verification link has been sent to your email address.',
35 | 'verify_title' => 'Verify Your Email Address',
36 |
37 | ];
38 |
--------------------------------------------------------------------------------
/resources/lang/en/common.php:
--------------------------------------------------------------------------------
1 | 'Unknown',
13 | ];
14 |
--------------------------------------------------------------------------------
/resources/lang/en/exception.php:
--------------------------------------------------------------------------------
1 | "Request have exception",
5 | "action" => "Action exception",
6 | "store" => "Not store database",
7 | "store_multiple" => "Not store multiple database",
8 | "update_multiple" => "Not update multiple database",
9 | "update" => "Not update database",
10 | "delete" => "Delete fail",
11 | "restore" => "Restore fail",
12 | "remove" => "Remove fail",
13 | "not_found" => "Item not exists",
14 | "not_owner" => "Not owner",
15 | "unknown_error" => "Unknown error",
16 | "data_invalid" => "Data invalid",
17 | // Role and permission exception
18 | 'not_have_role' => 'User does not have the right roles. Necessary roles are ":roles"',
19 | 'not_have_permission' => 'User does not have the right permissions. Necessary permissions are ":permissions"',
20 | 'not_have_role_and_permission' => 'User does not have the right permissions. Necessary permissions are ":permissions"',
21 | 'not_loggin' => 'User is not logged in.',
22 | 'there_no_role_name' => 'There is no permission named ":roleName"',
23 | 'there_no_role_id' => 'There is no permission with id ":roleId"',
24 | 'there_no_permission_name' => 'There is no permission named ":permissionName"',
25 | 'there_no_permission_id' => 'There is no permission with id ":permissionId"',
26 | ];
27 |
--------------------------------------------------------------------------------
/resources/lang/en/export.php:
--------------------------------------------------------------------------------
1 | [
5 | 'separation_required' => 'The Separation field is required!',
6 | 'encoding_required' => 'The Encoding field is required!',
7 | 'encoding_in' => 'Encoding field not on whitelist!',
8 | 'file_type_required' => 'The File Type field is required!',
9 | 'file_type_in' => 'The File Type field must be csv or xlsx',
10 | 'export_column_required' => 'The Export Column field is required!'
11 | ],
12 | 'header_export' => [
13 | 'id' => 'ID',
14 | 'name' => 'Name',
15 | 'created_at' => 'Created At',
16 | 'updated_at' => 'Update At',
17 | ],
18 | ];
19 |
--------------------------------------------------------------------------------
/resources/lang/en/http_message.php:
--------------------------------------------------------------------------------
1 | "Not Modified",
5 | "400" => "Invalid Request",
6 | "401" => "Unauthorized",
7 | "403" => "Access Denied",
8 | "404" => "Not Found",
9 | "405" => "Method not Allowed",
10 | "422" => "Validator error",
11 | "500" => "Internal Server Error",
12 | "502" => "Bad Gateway",
13 | "503" => "Service Unavailable",
14 | "504" => "Gateway Timeout",
15 | ];
16 |
--------------------------------------------------------------------------------
/resources/lang/en/import.php:
--------------------------------------------------------------------------------
1 | [
5 | 'file_required' => 'The import file is required !',
6 | 'file_mimes' => 'The import file must be a file of type :format',
7 | 'file_max' => 'The import file may not be greater than :max Kb.',
8 | 'success' => 'Data imported successfully !',
9 | 'error_row_name' => 'Name is invalid at row :row, column :column',
10 | 'error_header' => 'The import file header is missing or invalid',
11 | 'error_element' => 'Not enough fields at row :row',
12 | 'import_failed' => 'Integrity constraint violation. Import file failed',
13 | ],
14 | 'header_text' => [
15 | 'id' => 'ID',
16 | 'name' => 'Name',
17 | 'created_at' => 'Created At',
18 | ],
19 | 'index' => [
20 | 'title' => 'Import File',
21 | 'error_validation' => 'The validation error message',
22 | 'import' => 'Import',
23 | ],
24 | ];
25 |
--------------------------------------------------------------------------------
/resources/lang/en/pagination.php:
--------------------------------------------------------------------------------
1 | '« Previous',
17 | 'next' => 'Next »',
18 |
19 | ];
20 |
--------------------------------------------------------------------------------
/resources/lang/en/passwords.php:
--------------------------------------------------------------------------------
1 | 'Passwords must be at least eight characters and match the confirmation.',
17 | 'reset' => 'Your password has been reset!',
18 | 'sent' => 'We have e-mailed your password reset link!',
19 | 'token' => 'This password reset token is invalid.',
20 | 'user' => "We can't find a user with that e-mail address.",
21 |
22 | ];
23 |
--------------------------------------------------------------------------------
/resources/sass/_mixins.scss:
--------------------------------------------------------------------------------
1 | // ======================================================
2 | // Abstracts :: Mixins
3 | // ======================================================
4 |
5 | @mixin padding-none() {
6 | padding: 0;
7 | }
8 |
--------------------------------------------------------------------------------
/resources/sass/_variables.scss:
--------------------------------------------------------------------------------
1 |
2 | // Body
3 | $body-bg: #f8fafc;
4 |
5 | // Typography
6 | $font-family-sans-serif: "Nunito", sans-serif;
7 | $font-size-base: 0.9rem;
8 | $line-height-base: 1.6;
9 |
10 | // Colors
11 | $blue: #3490dc;
12 | $indigo: #6574cd;
13 | $purple: #9561e2;
14 | $pink: #f66d9b;
15 | $red: #e3342f;
16 | $orange: #f6993f;
17 | $yellow: #ffed4a;
18 | $green: #38c172;
19 | $teal: #4dc0b5;
20 | $cyan: #6cb2eb;
21 | $white: #fff;
22 | $black: #000;
23 | $gray-light: #f7f7f7;
24 |
--------------------------------------------------------------------------------
/resources/sass/app.scss:
--------------------------------------------------------------------------------
1 |
2 | // Fonts
3 | @import url('https://fonts.googleapis.com/css?family=Nunito');
4 |
5 | // Variables
6 | @import 'variables';
7 | @import 'mixins';
8 |
9 | // Bootstrap
10 | @import '~bootstrap/scss/bootstrap';
11 | @import '~bootstrap-vue/src/index.scss';
12 |
13 | .navbar-laravel {
14 | background-color: #fff;
15 | box-shadow: 0 2px 4px rgba(0, 0, 0, 0.04);
16 | }
17 |
--------------------------------------------------------------------------------
/resources/views/auth/passwords/email.blade.php:
--------------------------------------------------------------------------------
1 | @extends('layouts.app')
2 |
3 | @section('content')
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | @if (session('status'))
12 |
13 | {{ session('status') }}
14 |
15 | @endif
16 |
17 |
42 |
43 |
44 |
45 |
46 |
47 | @endsection
48 |
--------------------------------------------------------------------------------
/resources/views/auth/verify.blade.php:
--------------------------------------------------------------------------------
1 | @extends('layouts.app')
2 |
3 | @section('content')
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | @if (session('resent'))
12 |
13 | {{ __('auth.verify_link_success') }}
14 |
15 | @endif
16 |
17 | {{ __('auth.verify_link_notice') }}
18 | {{ __('auth.verify_link_not_receive') }},
{{ __('auth.verify_link_resend') }}.
19 |
20 |
21 |
22 |
23 |
24 | @endsection
25 |
--------------------------------------------------------------------------------
/resources/views/client.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | {{ config('app.name', 'Laravel') }}
12 |
13 |
14 |
15 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/resources/views/emails/mail_forgot_password.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/views/home.blade.php:
--------------------------------------------------------------------------------
1 | @extends('layouts.app')
2 |
3 | @section('content')
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | @if (session('status'))
12 |
13 | {{ session('status') }}
14 |
15 | @endif
16 |
17 | You are logged in!
18 |
19 |
20 |
21 |
22 |
23 | @endsection
24 |
--------------------------------------------------------------------------------
/resources/views/imports/index.blade.php:
--------------------------------------------------------------------------------
1 | @extends('layouts.app')
2 |
3 | @section('content')
4 |
5 | @if (count($errors))
6 |
7 | @foreach ($errors->all() as $err)
8 | {{ $err }}
9 | @endforeach
10 |
11 | @endif
12 | @if(Session::has('message'))
13 | {{ Session::get('message') }}
14 | @endif
15 |
27 | @endsection
28 |
--------------------------------------------------------------------------------
/resources/views/notification_template/chatwork.blade.php:
--------------------------------------------------------------------------------
1 | [toall][info][title]{{ $data->message }}[/title]Exception: {{ $data->context['exception'] ?: __('common.unknown') }}
2 | File: {{ $data->context['file'] ?: __('common.unknown') }}
3 | Line: {{ $data->context['line'] ?: __('common.unknown') }}
4 | User id: {{ isset($data->context['user_id']) ? $data->context['user_id'] : __('common.unknown') }}
5 | Route url: {{ $data->context['route_url'] ?: __('common.unknown') }}
6 | Git commit: {{ $data->context['commit'] ?: __('common.unknown') }}
7 | Server Ip: {{ $data->context['server_ip'] ?: __('common.unknown') }}
8 | Client Ip: {{ $data->context['client_ip'] ?: __('common.unknown') }}
9 | [/info]
10 |
--------------------------------------------------------------------------------
/resources/views/notification_template/slack.blade.php:
--------------------------------------------------------------------------------
1 | Exception: {{ $data->context['exception'] ?: __('common.unknown') }}
2 | File: {{ $data->context['file'] ?: __('common.unknown') }}
3 | Line: {{ $data->context['line'] ?: __('common.unknown') }}
4 | User id: {{ isset($data->context['user_id']) ? $data->context['user_id'] : __('common.unknown') }}
5 | Route url: {{ $data->context['route_url'] ?: __('common.unknown') }}
6 | Git commit: {{ $data->context['commit'] ?: __('common.unknown') }}
7 | Server Ip: {{ $data->context['server_ip'] ?: __('common.unknown') }}
8 | Client Ip: {{ $data->context['client_ip'] ?: __('common.unknown') }}
9 |
--------------------------------------------------------------------------------
/routes/api.php:
--------------------------------------------------------------------------------
1 | 'Api', 'prefix' => 'v1', 'as' => 'api.v1.'], function () {
17 | Route::group(['namespace' => 'Auth'], function () {
18 | Route::post('login', 'LoginController@login')->name('login');
19 | Route::post('token/refresh', 'LoginController@refreshToken')->name('token.refresh');
20 | Route::post('register', 'LoginController@register')->name('register');
21 | Route::post('password/email', 'ForgotPasswordController@sendResetTokenEmail')->name('password.reset.email');
22 | Route::post('password/reset', 'ForgotPasswordController@reset')->name('password.reset');
23 |
24 | Route::group(['middleware' => ['auth:api']], function () {
25 | Route::post('logout', 'LoginController@logout')->name('logout');
26 | });
27 | });
28 | });
29 |
--------------------------------------------------------------------------------
/routes/channels.php:
--------------------------------------------------------------------------------
1 | id === (int) $id;
16 | });
17 |
--------------------------------------------------------------------------------
/routes/console.php:
--------------------------------------------------------------------------------
1 | comment(Inspiring::quote());
18 | })->describe('Display an inspiring quote');
19 |
--------------------------------------------------------------------------------
/server.php:
--------------------------------------------------------------------------------
1 |
8 | */
9 |
10 | $uri = urldecode(
11 | parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH)
12 | );
13 |
14 | // This file allows us to emulate Apache's "mod_rewrite" functionality from the
15 | // built-in PHP web server. This provides a convenient way to test a Laravel
16 | // application without having installed a "real" web server software here.
17 | if ($uri !== '/' && file_exists(__DIR__.'/public'.$uri)) {
18 | return false;
19 | }
20 |
21 | require_once __DIR__.'/public/index.php';
22 |
--------------------------------------------------------------------------------
/storage/app/.gitignore:
--------------------------------------------------------------------------------
1 | *
2 | !public/
3 | !.gitignore
4 |
--------------------------------------------------------------------------------
/storage/app/public/.gitignore:
--------------------------------------------------------------------------------
1 | *
2 | !.gitignore
3 |
--------------------------------------------------------------------------------
/storage/framework/.gitignore:
--------------------------------------------------------------------------------
1 | config.php
2 | routes.php
3 | schedule-*
4 | compiled.php
5 | services.json
6 | events.scanned.php
7 | routes.scanned.php
8 | down
9 |
--------------------------------------------------------------------------------
/storage/framework/cache/.gitignore:
--------------------------------------------------------------------------------
1 | *
2 | !data/
3 | !.gitignore
4 |
--------------------------------------------------------------------------------
/storage/framework/cache/data/.gitignore:
--------------------------------------------------------------------------------
1 | *
2 | !.gitignore
3 |
--------------------------------------------------------------------------------
/storage/framework/sessions/.gitignore:
--------------------------------------------------------------------------------
1 | *
2 | !.gitignore
3 |
--------------------------------------------------------------------------------
/storage/framework/testing/.gitignore:
--------------------------------------------------------------------------------
1 | *
2 | !.gitignore
3 |
--------------------------------------------------------------------------------
/storage/framework/views/.gitignore:
--------------------------------------------------------------------------------
1 | *
2 | !.gitignore
3 |
--------------------------------------------------------------------------------
/storage/logs/.gitignore:
--------------------------------------------------------------------------------
1 | *
2 | !.gitignore
3 |
--------------------------------------------------------------------------------
/tests/CreatesApplication.php:
--------------------------------------------------------------------------------
1 | make(Kernel::class)->bootstrap();
19 |
20 | return $app;
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/tests/Feature/Http/Controller/Web/Auth/ForgetPasswordControllerTest.php:
--------------------------------------------------------------------------------
1 | get(route('password.request'));
19 | $response->assertSuccessful();
20 | $response->assertViewIs('auth.passwords.email');
21 | }
22 |
23 | public function testUserReceivesAnEmailWithAPasswordResetLink()
24 | {
25 | Mail::fake();
26 | $user = factory(User::class)->create([
27 | 'email' => 'phamtritrung39@gmail.com',
28 | 'password' => $password = '12345678',
29 | ]);
30 |
31 | $response = $this->post(route('password.email'), [
32 | 'email' => $user->email,
33 | ]);
34 |
35 | $response->assertStatus(302);
36 | $this->assertNotNull($token = DB::table('password_resets')->first());
37 |
38 | Mail::assertQueued(\App\Mail\MailForgotPassword::class, function ($mail) use ($user) {
39 | $fakeMail = new \ReflectionClass($mail);
40 | $mailUser = $fakeMail->getProperty('user');
41 | $mailUser->setAccessible(true);
42 | $mailClone = $mailUser->getValue($mail);
43 |
44 | return $mailClone->id === $user->id;
45 | });
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/tests/TestCase.php:
--------------------------------------------------------------------------------
1 | assertContains($message, $array);
21 | }
22 |
23 | /**
24 | * Check a message exist in array error of ValidationException
25 | *
26 | * @param Illuminate\Validation\ValidationException $e
27 | * @param message $message
28 | */
29 | public function assertValidatorExceptionContainErrorMsg(ValidationException $e, $message)
30 | {
31 | $allMessage = $e->validator->getMessageBag()->all();
32 | $this->assertContainErrorMessage($message, $allMessage);
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/tests/Unit/ExampleTest.php:
--------------------------------------------------------------------------------
1 | assertTrue(true);
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/tests/Unit/Http/Controller/Web/Auth/LoginControllerTest.php:
--------------------------------------------------------------------------------
1 | manager = app('session');
30 | $this->controller = $this->app->make('App\Http\Controllers\Web\Auth\LoginController');
31 | }
32 |
33 | public function testUserCanLoginWithCorrectCredentials()
34 | {
35 | $this->withoutMiddleware();
36 | $user = factory(User::class)->create([
37 | 'password' => $password = '123456',
38 | ]);
39 |
40 | $request = new LoginRequest();
41 |
42 | $request->headers->set('content-type', 'application/json');
43 | $request->setJson(new ParameterBag([
44 | 'email' => $user->email,
45 | 'password' => $password,
46 | ]));
47 | $request->setMethod('POST');
48 | $request->setLaravelSession($this->manager->driver());
49 |
50 | $response = $this->controller->login($request);
51 |
52 | $this->assertInstanceOf(RedirectResponse::class, $response);
53 | $this->assertEquals(route('home'), $response->headers->get('Location'));
54 | $this->assertAuthenticatedAs($user);
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/tests/Unit/Http/Controller/Web/Auth/RegisterControllerTest.php:
--------------------------------------------------------------------------------
1 | manager = app('session');
29 | $this->controller = $this->app->make('App\Http\Controllers\Web\Auth\RegisterController');
30 | }
31 |
32 | public function testUserCanRegister()
33 | {
34 | $this->withoutMiddleware();
35 |
36 | $data = [
37 | 'name' => 'John Doe',
38 | 'email' => 'john@example.com',
39 | 'password' => '12345678',
40 | 'password_confirmation' => '12345678',
41 | ];
42 |
43 | $request = new RegisterRequest();
44 |
45 | $request->headers->set('content-type', 'application/json');
46 | $request->setJson(new ParameterBag($data));
47 | $request->setMethod('POST');
48 | $request->setLaravelSession($this->manager->driver());
49 |
50 | $response = $this->controller->register($request);
51 |
52 | $this->assertInstanceOf(RedirectResponse::class, $response);
53 | $this->assertEquals(route('home'), $response->headers->get('Location'));
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/tests/Unit/Http/Middleware/PermissionMiddlewareTest.php:
--------------------------------------------------------------------------------
1 | permissionMiddleware = new PermissionMiddleware($this->app);
25 | }
26 |
27 | public function testGuestCanNotAccessRouteHasPermissionMiddleware()
28 | {
29 | $this->assertEquals($this->runMiddleware($this->permissionMiddleware, 'testPermission'), 403);
30 | }
31 |
32 | public function testUserCanAccessRouteHasRoleMiddleware()
33 | {
34 | $role = factory(Role::class)->create();
35 | $user = factory(User::class)->create();
36 | $permission = factory(Permission::class)->create();
37 | $user->assignRole($role);
38 | $role->assignPermission($permission);
39 | $this->actingAs($user);
40 |
41 | $this->assertEquals($this->runMiddleware($this->permissionMiddleware, $permission->name), 200);
42 | }
43 |
44 | protected function runMiddleware($middleware, $parameter)
45 | {
46 | try {
47 | return $middleware->handle(new Request(), function () {
48 | return (new Response())->setContent('');
49 | }, $parameter)->status();
50 | } catch (UnauthorizedException $e) {
51 | return $e->getStatusCode();
52 | }
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/tests/Unit/Http/Middleware/RoleMiddlewareTest.php:
--------------------------------------------------------------------------------
1 | roleMiddleware = new RoleMiddleware($this->app);
24 | }
25 |
26 | public function testGuestCanNotAccessRouteHasRoleMiddleware()
27 | {
28 | $this->assertEquals($this->runMiddleware($this->roleMiddleware, 'testRole'), 403);
29 | }
30 |
31 | public function testUserCanAccessRouteHasRoleMiddleware()
32 | {
33 | $role = factory(Role::class)->create();
34 | $user = factory(User::class)->create();
35 | $user->assignRole($role);
36 |
37 | $this->actingAs($user);
38 |
39 | $this->assertEquals($this->runMiddleware($this->roleMiddleware, $role->name), 200);
40 | }
41 |
42 | protected function runMiddleware($middleware, $parameter)
43 | {
44 | try {
45 | return $middleware->handle(new Request(), function () {
46 | return (new Response())->setContent('');
47 | }, $parameter)->status();
48 | } catch (UnauthorizedException $e) {
49 | return $e->getStatusCode();
50 | }
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/tests/Unit/Libraries/PermissionRegisterTest.php:
--------------------------------------------------------------------------------
1 | afterApplicationCreated(function () {
19 | $this->gate = app()->make(Gate::class);
20 | $this->permissionRegister = new PermissionRegister($this->gate);
21 | });
22 |
23 | parent::setUp();
24 | }
25 | /**
26 | * Register the permission check method on the gate.
27 | *
28 | * @return bool
29 | */
30 | public function testGateBeforeCallbacksReceiveClosure()
31 | {
32 | $this->permissionRegister->registerPermissions();
33 |
34 | $gate = new \ReflectionClass(app()->make(Gate::class));
35 |
36 | $beforeCallbacks = $gate->getProperty('beforeCallbacks');
37 | $beforeCallbacks->setAccessible(true);
38 |
39 | $this->assertEquals(true, collect($beforeCallbacks)->isNotEmpty());
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/tests/Unit/Models/PermissionTest.php:
--------------------------------------------------------------------------------
1 | runConfigurationAssertions(new Permission());
14 | }
15 |
16 | public function testRolesRelation()
17 | {
18 | $m = new Permission();
19 | $r = $m->roles();
20 | $this->assertBelongsToManyRelation($r, $m, new Role(), 'permission_id', 'role_id');
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/tests/Unit/Models/RoleTest.php:
--------------------------------------------------------------------------------
1 | runConfigurationAssertions(new Role());
15 | }
16 |
17 | public function testUsersRelation()
18 | {
19 | $m = new Role();
20 | $r = $m->users();
21 | $this->assertBelongsToManyRelation($r, $m, new User(), 'role_id', 'user_id');
22 | }
23 |
24 | public function testPermissionsRelation()
25 | {
26 | $m = new Role();
27 | $r = $m->permissions();
28 | $this->assertBelongsToManyRelation($r, $m, new Permission(), 'role_id', 'permission_id');
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/tests/Unit/Models/UserTest.php:
--------------------------------------------------------------------------------
1 | runConfigurationAssertions(
14 | new User(),
15 | [
16 | 'name',
17 | 'email',
18 | 'password',
19 | ],
20 | [
21 | 'password',
22 | 'remember_token',
23 | ],
24 | ['*'],
25 | [],
26 | [
27 | 'id' => 'int',
28 | 'email_verified_at' => 'datetime',
29 | ]
30 | );
31 | }
32 |
33 | public function testRolesRelation()
34 | {
35 | $m = new User();
36 | $r = $m->roles();
37 | $this->assertBelongsToManyRelation($r, $m, new Role(), 'user_id', 'role_id');
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/tests/Unit/Repositories/ExportRepositoryTest.php:
--------------------------------------------------------------------------------
1 | afterApplicationCreated(function () {
25 | $this->modelMock = Mockery::mock(Import::class);
26 | });
27 | parent::setUp();
28 | }
29 | public function testExportRepository()
30 | {
31 | $fields = [
32 | 'id',
33 | 'name',
34 | ];
35 | $repo = new ExportRepository($this->modelMock);
36 |
37 | $data = factory(Import::class)->make(['id' => 1]);
38 | $dataCollect = collect([$data]);
39 | $this->modelMock->shouldReceive('get')
40 | ->once()
41 | ->andReturn($dataCollect);
42 |
43 | $result = $repo->select($fields);
44 | $result = collect($result);
45 |
46 | $this->assertTrue($result->contains('id', $data->id));
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/tests/Unit/Repositories/ImportRepositoryTest.php:
--------------------------------------------------------------------------------
1 | allows()
32 | ->table()
33 | ->with(m::any())
34 | ->andReturnUsing(function ($table) use ($connection) {
35 | return (new Builder(
36 | $connection,
37 | new SQLiteGrammar(),
38 | new Processor()
39 | ))->from($table);
40 | });
41 | return $connection;
42 | }
43 |
44 | public function testInsertRepo()
45 | {
46 | $c = $this->mockDatabaseConnection();
47 | $repo = $this->makeRepository($c);
48 | $data = [
49 | 'id' => 15,
50 | 'name' => 'nam',
51 | 'created_at' => '09/04/19',
52 | ];
53 | $c->shouldReceive('insert')
54 | ->once()
55 | ->withArgs([
56 | 'insert into "imports" ("id", "name", "created_at") values (?, ?, ?)',
57 | array_values($data),
58 | ])
59 | ->andReturn(true);
60 | $result = $repo->insert($data);
61 | $this->assertEquals(true, $result);
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/tests/Unit/Services/ImportServiceTest.php:
--------------------------------------------------------------------------------
1 | afterApplicationCreated(function () {
23 | $this->importRepoMock = Mockery::mock(ImportRepositoryInterface::class);
24 | });
25 |
26 | parent::setUp();
27 | }
28 |
29 | public function testImportFileData()
30 | {
31 | $data = [
32 | 'id' => 15,
33 | 'name' => 'nam',
34 | 'created_at' => '09/04/19',
35 | ];
36 | $service = new ImportService($this->importRepoMock);
37 | $this->importRepoMock->shouldReceive('insert')
38 | ->once()
39 | ->andReturn(true);
40 | $response = $service->importFile($data);
41 | $this->assertEquals($response, true);
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/tests/files/data_check_header_rule.csv:
--------------------------------------------------------------------------------
1 | ID,Name,CreatedAt
2 | 15,以上です,19/09/01
3 | 16,さん,19/09/02
4 | 17,thanh,19/09/03
5 |
--------------------------------------------------------------------------------
/tests/files/data_check_row_rule.csv:
--------------------------------------------------------------------------------
1 | ID,Name,Created At
2 | 15,以上です,19/09/01
3 | 16,さん,19/09/02
4 | 17,19/09/03
5 |
--------------------------------------------------------------------------------
/tests/files/data_check_rule.csv:
--------------------------------------------------------------------------------
1 | ID,Name,Created At
2 | 15,以上です,19/09/01
3 | 16,さん,19/09/02
4 | 17,thanh,19/09/03
5 |
--------------------------------------------------------------------------------
/webpack.css.mix.js:
--------------------------------------------------------------------------------
1 | const mix = require('laravel-mix')
2 | const path = require('path')
3 | const mergeManifest = require('./mergeManifest')
4 |
5 | mix.extend('mergeManifest', mergeManifest)
6 | /*
7 | |--------------------------------------------------------------------------
8 | | Mix Asset Management
9 | |--------------------------------------------------------------------------
10 | |
11 | | Mix provides a clean, fluent API for defining some Webpack build steps
12 | | for your Laravel application. By default, we are compiling the Sass
13 | | file for the application as well as bundling up all the JS files.
14 | |
15 | */
16 |
17 | mix.webpackConfig({
18 | output: {
19 | chunkFilename: 'js/chunks/[name].js'
20 | },
21 | resolve: {
22 | alias : {
23 | sass: path.resolve(__dirname, 'resources/sass'),
24 | },
25 | },
26 | })
27 |
28 | mix.sass('resources/sass/app.scss', 'public/css')
29 | .mergeManifest();
30 |
31 | if (mix.inProduction()) {
32 | mix.version()
33 | } else {
34 | mix.sourceMaps()
35 | }
36 |
--------------------------------------------------------------------------------
/webpack.js.mix.js:
--------------------------------------------------------------------------------
1 | const mix = require('laravel-mix')
2 | const path = require('path')
3 | const mergeManifest = require('./mergeManifest')
4 |
5 | mix.extend('mergeManifest', mergeManifest)
6 | /*
7 | |--------------------------------------------------------------------------
8 | | Mix Asset Management
9 | |--------------------------------------------------------------------------
10 | |
11 | | Mix provides a clean, fluent API for defining some Webpack build steps
12 | | for your Laravel application. By default, we are compiling the Sass
13 | | file for the application as well as bundling up all the JS files.
14 | |
15 | */
16 |
17 | mix.webpackConfig({
18 | resolve: {
19 | alias: {
20 | '@': path.resolve(__dirname, 'resources/js'),
21 | 'sass': path.resolve(__dirname, 'resources/sass'),
22 | },
23 | }
24 | })
25 |
26 | mix.js('resources/js/app.js', 'public/js')
27 | .extract()
28 | .mergeManifest();
29 |
30 | if (mix.inProduction()) {
31 | mix.version()
32 | } else {
33 | mix.sourceMaps()
34 | }
35 |
--------------------------------------------------------------------------------