From 034d1c23fb233262b8e8c1fba2e8a8445ea0f32a Mon Sep 17 00:00:00 2001 From: xiaomlove Date: Wed, 28 Apr 2021 01:22:25 +0800 Subject: [PATCH] [exam] finish assign and remove --- admin/package-lock.json | 812 +++++++++++++++++++- admin/src/components/Header.vue | 2 +- admin/src/utils/api.js | 6 + admin/src/views/user/detail.vue | 18 +- admin/src/views/user/dialog-assign-exam.vue | 86 ++- app/Console/Commands/Test.php | 2 +- app/Exceptions/Handler.php | 24 +- app/Exceptions/NexusException.php | 8 + app/Http/Controllers/ExamUserController.php | 11 +- app/Http/Controllers/UserController.php | 8 +- app/Http/Kernel.php | 1 + app/Http/Middleware/Permission.php | 31 + app/Models/ExamUser.php | 2 +- app/Repositories/ExamRepository.php | 7 +- config/app.php | 2 +- routes/api.php | 2 +- 16 files changed, 988 insertions(+), 34 deletions(-) create mode 100644 app/Exceptions/NexusException.php create mode 100644 app/Http/Middleware/Permission.php diff --git a/admin/package-lock.json b/admin/package-lock.json index b31f054d..af994fb8 100644 --- a/admin/package-lock.json +++ b/admin/package-lock.json @@ -1,8 +1,818 @@ { "name": "admin", "version": "0.0.0", - "lockfileVersion": 1, + "lockfileVersion": 2, "requires": true, + "packages": { + "": { + "version": "0.0.0", + "dependencies": { + "axios": "^0.21.1", + "element-plus": "^1.0.2-beta.40", + "vue": "^3.0.5", + "vue-router": "^4.0.6" + }, + "devDependencies": { + "@vitejs/plugin-vue": "^1.2.1", + "@vue/compiler-sfc": "^3.0.5", + "sass": "^1.32.11", + "vite": "^2.1.5" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.12.11", + "resolved": "https://registry.npm.taobao.org/@babel/helper-validator-identifier/download/@babel/helper-validator-identifier-7.12.11.tgz?cache=0&sync_timestamp=1608076995361&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fhelper-validator-identifier%2Fdownload%2F%40babel%2Fhelper-validator-identifier-7.12.11.tgz", + "integrity": "sha1-yaHwIZF9y1zPDU5FPjmQIpgfye0=" + }, + "node_modules/@babel/parser": { + "version": "7.13.16", + "resolved": "https://registry.nlark.com/@babel/parser/download/@babel/parser-7.13.16.tgz?cache=0&sync_timestamp=1618917780280&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40babel%2Fparser%2Fdownload%2F%40babel%2Fparser-7.13.16.tgz", + "integrity": "sha1-DxgXmwRI5pObHz9cTDVaOpvN/Tc=", + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/types": { + "version": "7.13.17", + "resolved": "https://registry.nlark.com/@babel/types/download/@babel/types-7.13.17.tgz", + "integrity": "sha1-SAEKEVyfunWItEN91oyUaQErOLQ=", + "dependencies": { + "@babel/helper-validator-identifier": "^7.12.11", + "to-fast-properties": "^2.0.0" + } + }, + "node_modules/@popperjs/core": { + "version": "2.9.2", + "resolved": "https://registry.npm.taobao.org/@popperjs/core/download/@popperjs/core-2.9.2.tgz?cache=0&sync_timestamp=1617290098226&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40popperjs%2Fcore%2Fdownload%2F%40popperjs%2Fcore-2.9.2.tgz", + "integrity": "sha1-rep7aVPLs0ZRdmsFSEaOdDxqI1M=" + }, + "node_modules/@types/lodash": { + "version": "4.14.168", + "resolved": "https://registry.npm.taobao.org/@types/lodash/download/@types/lodash-4.14.168.tgz?cache=0&sync_timestamp=1613379158193&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40types%2Flodash%2Fdownload%2F%40types%2Flodash-4.14.168.tgz", + "integrity": "sha1-/iRjLnm3rePxMoka//hsql5c4Ag=" + }, + "node_modules/@vitejs/plugin-vue": { + "version": "1.2.1", + "resolved": "https://registry.npm.taobao.org/@vitejs/plugin-vue/download/@vitejs/plugin-vue-1.2.1.tgz?cache=0&sync_timestamp=1617152725801&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40vitejs%2Fplugin-vue%2Fdownload%2F%40vitejs%2Fplugin-vue-1.2.1.tgz", + "integrity": "sha1-beSUNvw0b4KaVmdgZkKOPwEVIqw=", + "dev": true, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/@vue/compiler-core": { + "version": "3.0.11", + "resolved": "https://registry.npm.taobao.org/@vue/compiler-core/download/@vue/compiler-core-3.0.11.tgz?cache=0&sync_timestamp=1617321553533&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40vue%2Fcompiler-core%2Fdownload%2F%40vue%2Fcompiler-core-3.0.11.tgz", + "integrity": "sha1-XvV55G17M2uHNSKHWNHCxQWq5po=", + "dependencies": { + "@babel/parser": "^7.12.0", + "@babel/types": "^7.12.0", + "@vue/shared": "3.0.11", + "estree-walker": "^2.0.1", + "source-map": "^0.6.1" + } + }, + "node_modules/@vue/compiler-dom": { + "version": "3.0.11", + "resolved": "https://registry.npm.taobao.org/@vue/compiler-dom/download/@vue/compiler-dom-3.0.11.tgz", + "integrity": "sha1-sV/ByQk3H9ZxdGAgulW12rSnMO4=", + "dependencies": { + "@vue/compiler-core": "3.0.11", + "@vue/shared": "3.0.11" + } + }, + "node_modules/@vue/compiler-sfc": { + "version": "3.0.11", + "resolved": "https://registry.npm.taobao.org/@vue/compiler-sfc/download/@vue/compiler-sfc-3.0.11.tgz", + "integrity": "sha1-zYyiFUuIlntSH1rTsQ9fi2tmVnk=", + "dev": true, + "dependencies": { + "@babel/parser": "^7.13.9", + "@babel/types": "^7.13.0", + "@vue/compiler-core": "3.0.11", + "@vue/compiler-dom": "3.0.11", + "@vue/compiler-ssr": "3.0.11", + "@vue/shared": "3.0.11", + "consolidate": "^0.16.0", + "estree-walker": "^2.0.1", + "hash-sum": "^2.0.0", + "lru-cache": "^5.1.1", + "magic-string": "^0.25.7", + "merge-source-map": "^1.1.0", + "postcss": "^8.1.10", + "postcss-modules": "^4.0.0", + "postcss-selector-parser": "^6.0.4", + "source-map": "^0.6.1" + } + }, + "node_modules/@vue/compiler-ssr": { + "version": "3.0.11", + "resolved": "https://registry.npm.taobao.org/@vue/compiler-ssr/download/@vue/compiler-ssr-3.0.11.tgz?cache=0&sync_timestamp=1617321554271&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40vue%2Fcompiler-ssr%2Fdownload%2F%40vue%2Fcompiler-ssr-3.0.11.tgz", + "integrity": "sha1-rFoF/RJXQS+mYHnII9ggO2qImhM=", + "dev": true, + "dependencies": { + "@vue/compiler-dom": "3.0.11", + "@vue/shared": "3.0.11" + } + }, + "node_modules/@vue/reactivity": { + "version": "3.0.11", + "resolved": "https://registry.npm.taobao.org/@vue/reactivity/download/@vue/reactivity-3.0.11.tgz?cache=0&sync_timestamp=1617321554569&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40vue%2Freactivity%2Fdownload%2F%40vue%2Freactivity-3.0.11.tgz", + "integrity": "sha1-B7WINJ/QViaxfzUAy+99S9tNvQs=", + "dependencies": { + "@vue/shared": "3.0.11" + } + }, + "node_modules/@vue/runtime-core": { + "version": "3.0.11", + "resolved": "https://registry.npm.taobao.org/@vue/runtime-core/download/@vue/runtime-core-3.0.11.tgz?cache=0&sync_timestamp=1617321945301&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40vue%2Fruntime-core%2Fdownload%2F%40vue%2Fruntime-core-3.0.11.tgz", + "integrity": "sha1-xS38as8yFUk2I1UsHCkZCAxWLkQ=", + "dependencies": { + "@vue/reactivity": "3.0.11", + "@vue/shared": "3.0.11" + } + }, + "node_modules/@vue/runtime-dom": { + "version": "3.0.11", + "resolved": "https://registry.npm.taobao.org/@vue/runtime-dom/download/@vue/runtime-dom-3.0.11.tgz?cache=0&sync_timestamp=1617321945517&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40vue%2Fruntime-dom%2Fdownload%2F%40vue%2Fruntime-dom-3.0.11.tgz", + "integrity": "sha1-elUt8hkHlCch/raWHEGOIippkzc=", + "dependencies": { + "@vue/runtime-core": "3.0.11", + "@vue/shared": "3.0.11", + "csstype": "^2.6.8" + } + }, + "node_modules/@vue/shared": { + "version": "3.0.11", + "resolved": "https://registry.npm.taobao.org/@vue/shared/download/@vue/shared-3.0.11.tgz?cache=0&sync_timestamp=1617321555263&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40vue%2Fshared%2Fdownload%2F%40vue%2Fshared-3.0.11.tgz", + "integrity": "sha1-INIt0Np9NYuyHBf5vehigVJkLHc=" + }, + "node_modules/anymatch": { + "version": "3.1.2", + "resolved": "https://registry.npm.taobao.org/anymatch/download/anymatch-3.1.2.tgz", + "integrity": "sha1-wFV8CWrzLxBhmPT04qODU343hxY=", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/async-validator": { + "version": "3.5.1", + "resolved": "https://registry.npm.taobao.org/async-validator/download/async-validator-3.5.1.tgz?cache=0&sync_timestamp=1605749896979&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fasync-validator%2Fdownload%2Fasync-validator-3.5.1.tgz", + "integrity": "sha1-zWK5aIskZfSEIOJ620d2CrG1VZ8=" + }, + "node_modules/axios": { + "version": "0.21.1", + "resolved": "https://registry.npm.taobao.org/axios/download/axios-0.21.1.tgz", + "integrity": "sha1-IlY0gZYvTWvemnbVFu8OXTwJsrg=", + "dependencies": { + "follow-redirects": "^1.10.0" + } + }, + "node_modules/big.js": { + "version": "5.2.2", + "resolved": "https://registry.npm.taobao.org/big.js/download/big.js-5.2.2.tgz", + "integrity": "sha1-ZfCvOC9Xi83HQr2cKB6cstd2gyg=", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npm.taobao.org/binary-extensions/download/binary-extensions-2.2.0.tgz?cache=0&sync_timestamp=1610299308660&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fbinary-extensions%2Fdownload%2Fbinary-extensions-2.2.0.tgz", + "integrity": "sha1-dfUC7q+f/eQvyYgpZFvk6na9ni0=", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npm.taobao.org/bluebird/download/bluebird-3.7.2.tgz?cache=0&sync_timestamp=1589682744631&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fbluebird%2Fdownload%2Fbluebird-3.7.2.tgz", + "integrity": "sha1-nyKcFb4nJFT/qXOs4NvueaGww28=", + "dev": true + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npm.taobao.org/braces/download/braces-3.0.2.tgz", + "integrity": "sha1-NFThpGLujVmeI23zNs2epPiv4Qc=", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/chokidar": { + "version": "3.5.1", + "resolved": "https://registry.npm.taobao.org/chokidar/download/chokidar-3.5.1.tgz?cache=0&sync_timestamp=1610719430924&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fchokidar%2Fdownload%2Fchokidar-3.5.1.tgz", + "integrity": "sha1-7pznu+vSt59J8wR5nVRo4x4U5oo=", + "dev": true, + "dependencies": { + "anymatch": "~3.1.1", + "braces": "~3.0.2", + "glob-parent": "~5.1.0", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.5.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.1" + } + }, + "node_modules/colorette": { + "version": "1.2.2", + "resolved": "https://registry.npm.taobao.org/colorette/download/colorette-1.2.2.tgz?cache=0&sync_timestamp=1614259623635&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcolorette%2Fdownload%2Fcolorette-1.2.2.tgz", + "integrity": "sha1-y8x51emcrqLb8Q6zom/Ys+as+pQ=", + "dev": true + }, + "node_modules/consolidate": { + "version": "0.16.0", + "resolved": "https://registry.npm.taobao.org/consolidate/download/consolidate-0.16.0.tgz?cache=0&sync_timestamp=1599596863404&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fconsolidate%2Fdownload%2Fconsolidate-0.16.0.tgz", + "integrity": "sha1-oRhkdokw8vGUMWYKZZBmaPX73BY=", + "dev": true, + "dependencies": { + "bluebird": "^3.7.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/cssesc/download/cssesc-3.0.0.tgz", + "integrity": "sha1-N3QZGZA7hoVl4cCep0dEXNGJg+4=", + "dev": true, + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/csstype": { + "version": "2.6.17", + "resolved": "https://registry.nlark.com/csstype/download/csstype-2.6.17.tgz?cache=0&sync_timestamp=1618818466657&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fcsstype%2Fdownload%2Fcsstype-2.6.17.tgz", + "integrity": "sha1-TPMOuH4dGgBdi2UQ+VKSQT9qHA4=" + }, + "node_modules/dayjs": { + "version": "1.10.4", + "resolved": "https://registry.npm.taobao.org/dayjs/download/dayjs-1.10.4.tgz?cache=0&sync_timestamp=1611310021152&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdayjs%2Fdownload%2Fdayjs-1.10.4.tgz", + "integrity": "sha1-jlRKm4aD9heD9XCYCoqA6vVKseI=" + }, + "node_modules/element-plus": { + "version": "1.0.2-beta.40", + "resolved": "https://registry.npm.taobao.org/element-plus/download/element-plus-1.0.2-beta.40.tgz", + "integrity": "sha1-MPybFhSWrlh/q4YjXIC3KOpD2Qk=", + "dependencies": { + "@popperjs/core": "^2.4.4", + "@types/lodash": "^4.14.161", + "async-validator": "^3.4.0", + "dayjs": "1.x", + "lodash": "^4.17.20", + "mitt": "^2.1.0", + "normalize-wheel": "^1.0.1", + "resize-observer-polyfill": "^1.5.1" + } + }, + "node_modules/emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/emojis-list/download/emojis-list-3.0.0.tgz", + "integrity": "sha1-VXBmIEatKeLpFucariYKvf9Pang=", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/esbuild": { + "version": "0.9.7", + "resolved": "https://registry.npm.taobao.org/esbuild/download/esbuild-0.9.7.tgz", + "integrity": "sha1-6g1jnL5LiOwl++1Nb/AMjXiO9ws=", + "dev": true, + "bin": { + "esbuild": "bin/esbuild" + } + }, + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npm.taobao.org/estree-walker/download/estree-walker-2.0.2.tgz?cache=0&sync_timestamp=1611956983677&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Festree-walker%2Fdownload%2Festree-walker-2.0.2.tgz", + "integrity": "sha1-UvAQF4wqTBF6d1fP6UKtt9LaTKw=" + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npm.taobao.org/fill-range/download/fill-range-7.0.1.tgz", + "integrity": "sha1-GRmmp8df44ssfHflGYU12prN2kA=", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/follow-redirects": { + "version": "1.13.3", + "resolved": "https://registry.npm.taobao.org/follow-redirects/download/follow-redirects-1.13.3.tgz", + "integrity": "sha1-5VmK1QF0wbxOhyMB6CrCzZf5Amc=", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npm.taobao.org/fsevents/download/fsevents-2.3.2.tgz", + "integrity": "sha1-ilJveLj99GI7cJ4Ll1xSwkwC/Ro=", + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npm.taobao.org/function-bind/download/function-bind-1.1.1.tgz", + "integrity": "sha1-pWiZ0+o8m6uHS7l3O3xe3pL0iV0=", + "dev": true + }, + "node_modules/generic-names": { + "version": "2.0.1", + "resolved": "https://registry.npm.taobao.org/generic-names/download/generic-names-2.0.1.tgz?cache=0&sync_timestamp=1603542269880&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fgeneric-names%2Fdownload%2Fgeneric-names-2.0.1.tgz", + "integrity": "sha1-+KN46tLMqno08DF7BVVIMq5BuHI=", + "dev": true, + "dependencies": { + "loader-utils": "^1.1.0" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npm.taobao.org/glob-parent/download/glob-parent-5.1.2.tgz?cache=0&sync_timestamp=1615065997979&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fglob-parent%2Fdownload%2Fglob-parent-5.1.2.tgz", + "integrity": "sha1-hpgyxYA0/mikCTwX3BXoNA2EAcQ=", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npm.taobao.org/has/download/has-1.0.3.tgz", + "integrity": "sha1-ci18v8H2qoJB8W3YFOAR4fQeh5Y=", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/hash-sum": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/hash-sum/download/hash-sum-2.0.0.tgz", + "integrity": "sha1-gdAbtd6OpKIUrV1urRtSNGCwtFo=", + "dev": true + }, + "node_modules/icss-replace-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npm.taobao.org/icss-replace-symbols/download/icss-replace-symbols-1.1.0.tgz", + "integrity": "sha1-Bupvg2ead0njhs/h/oEq5dsiPe0=", + "dev": true + }, + "node_modules/icss-utils": { + "version": "5.1.0", + "resolved": "https://registry.npm.taobao.org/icss-utils/download/icss-utils-5.1.0.tgz?cache=0&sync_timestamp=1605801291394&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ficss-utils%2Fdownload%2Ficss-utils-5.1.0.tgz", + "integrity": "sha1-xr5oWKvQE9do6YNmrkfiXViHsa4=", + "dev": true, + "engines": { + "node": "^10 || ^12 || >= 14" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npm.taobao.org/is-binary-path/download/is-binary-path-2.1.0.tgz", + "integrity": "sha1-6h9/O4DwZCNug0cPhsCcJU+0Wwk=", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-core-module": { + "version": "2.2.0", + "resolved": "https://registry.npm.taobao.org/is-core-module/download/is-core-module-2.2.0.tgz?cache=0&sync_timestamp=1606411622542&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fis-core-module%2Fdownload%2Fis-core-module-2.2.0.tgz", + "integrity": "sha1-lwN+89UiJNhRY/VZeytj2a/tmBo=", + "dev": true, + "dependencies": { + "has": "^1.0.3" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npm.taobao.org/is-extglob/download/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npm.taobao.org/is-glob/download/is-glob-4.0.1.tgz", + "integrity": "sha1-dWfb6fL14kZ7x3q4PEopSCQHpdw=", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npm.taobao.org/is-number/download/is-number-7.0.0.tgz", + "integrity": "sha1-dTU0W4lnNNX4DE0GxQlVUnoU8Ss=", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/json5": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/json5/download/json5-1.0.1.tgz", + "integrity": "sha1-d5+wAYYE+oVOrL9iUhgNg1Q+Pb4=", + "dev": true, + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npm.taobao.org/loader-utils/download/loader-utils-1.4.0.tgz", + "integrity": "sha1-xXm140yzSxp07cbB+za/o3HVphM=", + "dev": true, + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npm.taobao.org/lodash/download/lodash-4.17.21.tgz?cache=0&sync_timestamp=1613835838133&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Flodash%2Fdownload%2Flodash-4.17.21.tgz", + "integrity": "sha1-Z5WRxWTDv/quhFTPCz3zcMPWkRw=" + }, + "node_modules/lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npm.taobao.org/lodash.camelcase/download/lodash.camelcase-4.3.0.tgz", + "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=", + "dev": true + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npm.taobao.org/lru-cache/download/lru-cache-5.1.1.tgz?cache=0&sync_timestamp=1594427582110&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Flru-cache%2Fdownload%2Flru-cache-5.1.1.tgz", + "integrity": "sha1-HaJ+ZxAnGUdpXa9oSOhH8B2EuSA=", + "dev": true, + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/magic-string": { + "version": "0.25.7", + "resolved": "https://registry.npm.taobao.org/magic-string/download/magic-string-0.25.7.tgz", + "integrity": "sha1-P0l9b9NMZpxnmNy4IfLvMfVEUFE=", + "dev": true, + "dependencies": { + "sourcemap-codec": "^1.4.4" + } + }, + "node_modules/merge-source-map": { + "version": "1.1.0", + "resolved": "https://registry.npm.taobao.org/merge-source-map/download/merge-source-map-1.1.0.tgz", + "integrity": "sha1-L93n5gIJOfcJBqaPLXrmheTIxkY=", + "dev": true, + "dependencies": { + "source-map": "^0.6.1" + } + }, + "node_modules/minimist": { + "version": "1.2.5", + "resolved": "https://registry.npm.taobao.org/minimist/download/minimist-1.2.5.tgz?cache=0&sync_timestamp=1589682820731&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fminimist%2Fdownload%2Fminimist-1.2.5.tgz", + "integrity": "sha1-Z9ZgFLZqaoqqDAg8X9WN9OTpdgI=", + "dev": true + }, + "node_modules/mitt": { + "version": "2.1.0", + "resolved": "https://registry.npm.taobao.org/mitt/download/mitt-2.1.0.tgz?cache=0&sync_timestamp=1594823636076&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fmitt%2Fdownload%2Fmitt-2.1.0.tgz", + "integrity": "sha1-90BXfCMXbGIFsSGylzUU6t4bIjA=" + }, + "node_modules/nanoid": { + "version": "3.1.22", + "resolved": "https://registry.npm.taobao.org/nanoid/download/nanoid-3.1.22.tgz", + "integrity": "sha1-s1+Pt9FRmQqK69WqUBXAPPcm+EQ=", + "dev": true, + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/normalize-path/download/normalize-path-3.0.0.tgz", + "integrity": "sha1-Dc1p/yOhybEf0JeDFmRKA4ghamU=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-wheel": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/normalize-wheel/download/normalize-wheel-1.0.1.tgz", + "integrity": "sha1-rsiGr/2wRQcNhWRH32Ls+GFG7EU=" + }, + "node_modules/path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npm.taobao.org/path-parse/download/path-parse-1.0.6.tgz", + "integrity": "sha1-1i27VnlAXXLEc37FhgDp3c8G0kw=", + "dev": true + }, + "node_modules/picomatch": { + "version": "2.2.3", + "resolved": "https://registry.npm.taobao.org/picomatch/download/picomatch-2.2.3.tgz", + "integrity": "sha1-RlVH81nMwgbTxI5Goby4m/fuYZ0=", + "dev": true, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/postcss": { + "version": "8.2.10", + "resolved": "https://registry.npm.taobao.org/postcss/download/postcss-8.2.10.tgz?cache=0&sync_timestamp=1618159223724&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpostcss%2Fdownload%2Fpostcss-8.2.10.tgz", + "integrity": "sha1-ynoEKqiv9JSzNND/Pp53B59vcCs=", + "dev": true, + "dependencies": { + "colorette": "^1.2.2", + "nanoid": "^3.1.22", + "source-map": "^0.6.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-modules": { + "version": "4.0.0", + "resolved": "https://registry.npm.taobao.org/postcss-modules/download/postcss-modules-4.0.0.tgz", + "integrity": "sha1-K8fydquI8/Gw+t9svXdy1DtfO5s=", + "dev": true, + "dependencies": { + "generic-names": "^2.0.1", + "icss-replace-symbols": "^1.1.0", + "lodash.camelcase": "^4.3.0", + "postcss-modules-extract-imports": "^3.0.0", + "postcss-modules-local-by-default": "^4.0.0", + "postcss-modules-scope": "^3.0.0", + "postcss-modules-values": "^4.0.0", + "string-hash": "^1.1.1" + } + }, + "node_modules/postcss-modules-extract-imports": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/postcss-modules-extract-imports/download/postcss-modules-extract-imports-3.0.0.tgz?cache=0&sync_timestamp=1602588245463&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpostcss-modules-extract-imports%2Fdownload%2Fpostcss-modules-extract-imports-3.0.0.tgz", + "integrity": "sha1-zaHwR8CugMl9vijD52pDuIAldB0=", + "dev": true, + "engines": { + "node": "^10 || ^12 || >= 14" + } + }, + "node_modules/postcss-modules-local-by-default": { + "version": "4.0.0", + "resolved": "https://registry.npm.taobao.org/postcss-modules-local-by-default/download/postcss-modules-local-by-default-4.0.0.tgz?cache=0&sync_timestamp=1602587568476&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpostcss-modules-local-by-default%2Fdownload%2Fpostcss-modules-local-by-default-4.0.0.tgz", + "integrity": "sha1-67tU+uFZjuz99pGgKz/zs5ClpRw=", + "dev": true, + "dependencies": { + "icss-utils": "^5.0.0", + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.1.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + } + }, + "node_modules/postcss-modules-scope": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/postcss-modules-scope/download/postcss-modules-scope-3.0.0.tgz?cache=0&sync_timestamp=1602593260387&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpostcss-modules-scope%2Fdownload%2Fpostcss-modules-scope-3.0.0.tgz", + "integrity": "sha1-nvMVFFbTu/oSDKRImN/Kby+gHwY=", + "dev": true, + "dependencies": { + "postcss-selector-parser": "^6.0.4" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + } + }, + "node_modules/postcss-modules-values": { + "version": "4.0.0", + "resolved": "https://registry.npm.taobao.org/postcss-modules-values/download/postcss-modules-values-4.0.0.tgz?cache=0&sync_timestamp=1602586230505&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpostcss-modules-values%2Fdownload%2Fpostcss-modules-values-4.0.0.tgz", + "integrity": "sha1-18Xn5ow7s8myfL9Iyguz/7RgLJw=", + "dev": true, + "dependencies": { + "icss-utils": "^5.0.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.0.5", + "resolved": "https://registry.nlark.com/postcss-selector-parser/download/postcss-selector-parser-6.0.5.tgz", + "integrity": "sha1-BC104Tfbg+bylHEglstBP1qmEsQ=", + "dev": true, + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.1.0", + "resolved": "https://registry.npm.taobao.org/postcss-value-parser/download/postcss-value-parser-4.1.0.tgz", + "integrity": "sha1-RD9qIM7WSBor2k+oUypuVdeJoss=", + "dev": true + }, + "node_modules/readdirp": { + "version": "3.5.0", + "resolved": "https://registry.npm.taobao.org/readdirp/download/readdirp-3.5.0.tgz?cache=0&sync_timestamp=1615717369278&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Freaddirp%2Fdownload%2Freaddirp-3.5.0.tgz", + "integrity": "sha1-m6dMAZsV02UnjS6Ru4xI17TULJ4=", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/resize-observer-polyfill": { + "version": "1.5.1", + "resolved": "https://registry.npm.taobao.org/resize-observer-polyfill/download/resize-observer-polyfill-1.5.1.tgz", + "integrity": "sha1-DpAg3T0hAkRY1OvSfiPkAmmBBGQ=" + }, + "node_modules/resolve": { + "version": "1.20.0", + "resolved": "https://registry.npm.taobao.org/resolve/download/resolve-1.20.0.tgz?cache=0&sync_timestamp=1613054822645&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fresolve%2Fdownload%2Fresolve-1.20.0.tgz", + "integrity": "sha1-YpoBP7P3B1XW8LeTXMHCxTeLGXU=", + "dev": true, + "dependencies": { + "is-core-module": "^2.2.0", + "path-parse": "^1.0.6" + } + }, + "node_modules/rollup": { + "version": "2.45.2", + "resolved": "https://registry.npm.taobao.org/rollup/download/rollup-2.45.2.tgz?cache=0&sync_timestamp=1618288771153&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Frollup%2Fdownload%2Frollup-2.45.2.tgz", + "integrity": "sha1-j7hZF8nzVgVyDpIyjzzL+6b3i0g=", + "dev": true, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=10.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.1" + } + }, + "node_modules/sass": { + "version": "1.32.11", + "resolved": "https://registry.nlark.com/sass/download/sass-1.32.11.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fsass%2Fdownload%2Fsass-1.32.11.tgz", + "integrity": "sha1-sjaz6lXHZgLC7yvQRF8NtYG6ohg=", + "dev": true, + "dependencies": { + "chokidar": ">=3.0.0 <4.0.0" + }, + "bin": { + "sass": "sass.js" + }, + "engines": { + "node": ">=8.9.0" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npm.taobao.org/source-map/download/source-map-0.6.1.tgz?cache=0&sync_timestamp=1589682764497&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsource-map%2Fdownload%2Fsource-map-0.6.1.tgz", + "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sourcemap-codec": { + "version": "1.4.8", + "resolved": "https://registry.npm.taobao.org/sourcemap-codec/download/sourcemap-codec-1.4.8.tgz", + "integrity": "sha1-6oBL2UhXQC5pktBaOO8a41qatMQ=", + "dev": true + }, + "node_modules/string-hash": { + "version": "1.1.3", + "resolved": "https://registry.npm.taobao.org/string-hash/download/string-hash-1.1.3.tgz", + "integrity": "sha1-6Kr8CsGFW0Zmkp7X3RJ1311sgRs=", + "dev": true + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/to-fast-properties/download/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "engines": { + "node": ">=4" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npm.taobao.org/to-regex-range/download/to-regex-range-5.0.1.tgz", + "integrity": "sha1-FkjESq58jZiKMmAY7XL1tN0DkuQ=", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npm.taobao.org/util-deprecate/download/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "node_modules/vite": { + "version": "2.2.1", + "resolved": "https://registry.nlark.com/vite/download/vite-2.2.1.tgz", + "integrity": "sha1-kMSB9pNx8yhn2GpqYjuwZLh2rT0=", + "dev": true, + "dependencies": { + "esbuild": "^0.9.3", + "postcss": "^8.2.1", + "resolve": "^1.19.0", + "rollup": "^2.38.5" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": ">=12.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.1" + } + }, + "node_modules/vue": { + "version": "3.0.11", + "resolved": "https://registry.npm.taobao.org/vue/download/vue-3.0.11.tgz", + "integrity": "sha1-yC+VlMv03MhpJB1MjdPgjZqPS18=", + "dependencies": { + "@vue/compiler-dom": "3.0.11", + "@vue/runtime-dom": "3.0.11", + "@vue/shared": "3.0.11" + } + }, + "node_modules/vue-router": { + "version": "4.0.6", + "resolved": "https://registry.nlark.com/vue-router/download/vue-router-4.0.6.tgz", + "integrity": "sha1-kXUNtQfSZkLyJbDsYGRWjl/kSNY=" + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npm.taobao.org/yallist/download/yallist-3.1.1.tgz", + "integrity": "sha1-27fa+b/YusmrRev2ArjLrQ1dCP0=", + "dev": true + } + }, "dependencies": { "@babel/helper-validator-identifier": { "version": "7.12.11", diff --git a/admin/src/components/Header.vue b/admin/src/components/Header.vue index 5eeb9463..6bed98ee 100644 --- a/admin/src/components/Header.vue +++ b/admin/src/components/Header.vue @@ -46,7 +46,7 @@ export default { }) onMounted(() => { console.log("Head onMounted!") - // console.log(props, context) + console.log(props, context) }) watch( () => route, diff --git a/admin/src/utils/api.js b/admin/src/utils/api.js index bb939399..254871cd 100644 --- a/admin/src/utils/api.js +++ b/admin/src/utils/api.js @@ -35,6 +35,9 @@ const api = { storeUser: (params = {}) => { return axios.post('user', params); }, + listUserMatchExams: (params = {}) => { + return axios.get('user-match-exams', {params: params}); + }, listExam: (params = {}) => { return axios.get('exam', {params: params}); @@ -63,6 +66,9 @@ const api = { deleteExamUser: (id) => { return axios.delete('exam-users/' + id); }, + storeExamUser: (params) => { + return axios.post('exam-users', params); + }, } export default api diff --git a/admin/src/views/user/detail.vue b/admin/src/views/user/detail.vue index 258d73ef..490438e9 100644 --- a/admin/src/views/user/detail.vue +++ b/admin/src/views/user/detail.vue @@ -112,6 +112,7 @@ + diff --git a/app/Console/Commands/Test.php b/app/Console/Commands/Test.php index a3ae66ba..e2c2ac56 100644 --- a/app/Console/Commands/Test.php +++ b/app/Console/Commands/Test.php @@ -45,7 +45,7 @@ class Test extends Command public function handle() { $rep = new ExamRepository(); - $r = $rep->addProgress(1, 1, 250, 1); + $r = $rep->addProgress(15, 1, 250, 1); dd($r); } } diff --git a/app/Exceptions/Handler.php b/app/Exceptions/Handler.php index 9805e14a..2bb44954 100644 --- a/app/Exceptions/Handler.php +++ b/app/Exceptions/Handler.php @@ -3,9 +3,11 @@ namespace App\Exceptions; use Illuminate\Auth\AuthenticationException; +use Illuminate\Database\Eloquent\ModelNotFoundException; use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler; use Illuminate\Http\JsonResponse; use Illuminate\Support\Arr; +use Illuminate\Validation\UnauthorizedException; use Illuminate\Validation\ValidationException; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; use Throwable; @@ -47,6 +49,10 @@ class Handler extends ExceptionHandler return response()->json(fail($e->getMessage(), $e->guards()), 401); }); + $this->renderable(function (UnauthorizedException $e) { + return response()->json(fail($e->getMessage(), request()->all()), 403); + }); + $this->renderable(function (ValidationException $exception) { $errors = $exception->errors(); $msg = Arr::first(Arr::first($errors)); @@ -54,7 +60,9 @@ class Handler extends ExceptionHandler }); $this->renderable(function (NotFoundHttpException $e) { - return response()->json(fail('No query result.', request()->all()), 404); + if ($e->getPrevious() && $e->getPrevious() instanceof ModelNotFoundException) { + return response()->json(fail('No query result.', request()->all()), 404); + } }); } @@ -76,11 +84,23 @@ class Handler extends ExceptionHandler } return new JsonResponse( fail($msg, $data), - $this->isHttpException($e) ? $e->getStatusCode() : 500, + $this->getHttpStatusCode($e), $this->isHttpException($e) ? $e->getHeaders() : [], JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES ); } + protected function getHttpStatusCode(Throwable $e) + { + if ($e instanceof \InvalidArgumentException || $e instanceof NexusException) { + return 200; + } + if ($this->isHttpException($e)) { + return $e->getStatusCode(); + } + return 500; + + } + } diff --git a/app/Exceptions/NexusException.php b/app/Exceptions/NexusException.php new file mode 100644 index 00000000..420c3a6c --- /dev/null +++ b/app/Exceptions/NexusException.php @@ -0,0 +1,8 @@ + 'required', ]; $request->validate($rules); - $result = $this->repository->assignToUser($request->uid, $request->exam_id, $request->begin, $request->end); - $resource = new ExamResource($result); - return $this->success($resource); + $timeRange = $request->get('time_range', []); + $begin = isset($timeRange[0]) ? Carbon::parse($timeRange[0])->toDateTimeString() : null; + $end = isset($timeRange[1])? Carbon::parse($timeRange[1])->toDateTimeString() : null; + + $result = $this->repository->assignToUser($request->uid, $request->exam_id, $begin, $end); + $resource = new ExamUserResource($result); + return $this->success($resource, 'Assign exam success!'); } /** diff --git a/app/Http/Controllers/UserController.php b/app/Http/Controllers/UserController.php index 239662be..d00ed0b5 100644 --- a/app/Http/Controllers/UserController.php +++ b/app/Http/Controllers/UserController.php @@ -114,11 +114,13 @@ class UserController extends Controller return $this->success($resource); } - public function matchExams() + public function matchExams(Request $request) { - $id = Auth::id(); + $request->validate([ + 'uid' => 'required', + ]); $examRepository = new ExamRepository(); - $result = $examRepository->listMatchExam($id); + $result = $examRepository->listMatchExam($request->uid); $resource = ExamResource::collection($result); return $this->success($resource); } diff --git a/app/Http/Kernel.php b/app/Http/Kernel.php index 30020a50..567176cc 100644 --- a/app/Http/Kernel.php +++ b/app/Http/Kernel.php @@ -62,5 +62,6 @@ class Kernel extends HttpKernel 'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class, 'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class, 'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class, + 'permission' => \App\Http\Middleware\Permission::class, ]; } diff --git a/app/Http/Middleware/Permission.php b/app/Http/Middleware/Permission.php new file mode 100644 index 00000000..1f4043cc --- /dev/null +++ b/app/Http/Middleware/Permission.php @@ -0,0 +1,31 @@ +user(); + $targetClass = User::CLASS_MODERATOR; + $log = sprintf('user: %s, class: %s, target class: %s', $user->id, $user->class, $targetClass); + if (!$user || $user->class < $targetClass) { + do_log("$log, denied!"); + throw new UnauthorizedException('Unauthorized!'); + } + do_log("$log, pass!"); + return $next($request); + } +} diff --git a/app/Models/ExamUser.php b/app/Models/ExamUser.php index c6d34a3a..b9b41375 100644 --- a/app/Models/ExamUser.php +++ b/app/Models/ExamUser.php @@ -4,7 +4,7 @@ namespace App\Models; class ExamUser extends NexusModel { - protected $fillable = ['exam_id', 'uid', 'status', 'progress']; + protected $fillable = ['exam_id', 'uid', 'status', 'progress', 'begin', 'end']; public $timestamps = true; diff --git a/app/Repositories/ExamRepository.php b/app/Repositories/ExamRepository.php index 2381dd11..9901935e 100644 --- a/app/Repositories/ExamRepository.php +++ b/app/Repositories/ExamRepository.php @@ -1,6 +1,7 @@ listMatchExam($uid); if ($exams->count() > 1) { do_log(last_query()); - throw new \LogicException("Match exam more than 1."); + throw new NexusException("Match exam more than 1."); } $exam = $exams->first(); } if (!$exam) { - throw new \LogicException("No valid exam."); + throw new NexusException("No valid exam."); } $user = User::query()->findOrFail($uid); $exists = $user->exams()->where('exam_id', $exam->id)->exists(); if ($exists) { - throw new \LogicException("Exam: {$exam->id} already assign to user: {$user->id}"); + throw new NexusException("Exam: {$exam->id} already assign to user: {$user->id}"); } $data = [ 'exam_id' => $exam->id, diff --git a/config/app.php b/config/app.php index f572b646..6079b6d5 100644 --- a/config/app.php +++ b/config/app.php @@ -67,7 +67,7 @@ return [ | */ - 'timezone' => 'UTC', + 'timezone' => env('TIMEZONE', 'UTC'), /* |-------------------------------------------------------------------------- diff --git a/routes/api.php b/routes/api.php index 9a47fca3..df1a24f7 100644 --- a/routes/api.php +++ b/routes/api.php @@ -14,7 +14,7 @@ use Illuminate\Support\Facades\Route; | */ -Route::group(['middleware' => ['auth:sanctum']], function () { +Route::group(['middleware' => ['auth:sanctum', 'permission']], function () { Route::post('logout', [\App\Http\Controllers\AuthenticateController::class, 'logout']); Route::resource('agent-allow', \App\Http\Controllers\AgentAllowController::class);