diff --git a/admin/src/components/Header.vue b/admin/src/components/Header.vue index dc96f5ec..67c671d5 100644 --- a/admin/src/components/Header.vue +++ b/admin/src/components/Header.vue @@ -14,14 +14,14 @@
-

登录名:{{ userInfo && userInfo.loginUserName || '' }}

-

昵称:{{ userInfo && userInfo.nickName || '' }}

- 退出 +

Username:{{ userInfo && userInfo.username || '' }}

+

Email:{{ userInfo && userInfo.email || '' }}

+ Logout
@@ -33,6 +33,8 @@ import { onMounted, reactive, toRefs } from 'vue' import { useRouter } from 'vue-router' import axios from '../utils/axios' import { localRemove, pathMap } from '../utils' +import api from "../utils/api"; + export default { name: 'Header', setup() { @@ -44,18 +46,18 @@ export default { }) onMounted(() => { const pathname = window.location.hash.split('/')[1] || '' - if (!['login'].includes(pathname)) { - // getUserInfo() - } + console.log("pathname: ", pathname) + getUserInfo() }) const getUserInfo = async () => { - const userInfo = await axios.get('/adminUser/profile') - state.userInfo = userInfo + const userInfo = await api.getUserBase() + console.log(userInfo) + state.userInfo = userInfo.data } const logout = () => { - axios.delete('/logout').then(() => { + api.logout().then(() => { localRemove('token') - router.push({ path: '/login' }) + router.push({ name: 'login' }) }) } const back = () => { diff --git a/admin/src/utils/api.js b/admin/src/utils/api.js index 5164b3ad..6776db34 100644 --- a/admin/src/utils/api.js +++ b/admin/src/utils/api.js @@ -1,6 +1,12 @@ import axios from "./axios"; const api = { + login: (params = {}) => { + return axios.post('login', params); + }, + logout: (params = {}) => { + return axios.post('logout'); + }, listAllowAgent: (params = {}) => { return axios.get('agent-allow', {params: params}); }, @@ -20,6 +26,9 @@ const api = { listUser: (params = {}) => { return axios.get('user', {params: params}); }, + getUserBase: (params = {}) => { + return axios.get('user-base', {params: params}); + }, storeUser: (params = {}) => { return axios.post('user', params); }, diff --git a/admin/src/utils/axios.js b/admin/src/utils/axios.js index 6fa9e907..e00aba6c 100644 --- a/admin/src/utils/axios.js +++ b/admin/src/utils/axios.js @@ -1,11 +1,13 @@ import axios from 'axios' import { ElMessage } from 'element-plus' +import {localGet} from "./index"; -axios.defaults.baseURL = 'http://nexus-php8.tinyhd.net' +axios.defaults.baseURL = 'http://nexus-php8.tinyhd.net/api' axios.defaults.withCredentials = true axios.defaults.headers['X-Requested-With'] = 'XMLHttpRequest' axios.defaults.headers['Content-Type'] = 'application/json' axios.defaults.headers['Accept'] = 'application/json' +axios.defaults.headers['Authorization'] = 'Bearer ' + localGet('token') // 请求拦截器,内部根据返回值,重新组装,统一管理。 axios.interceptors.response.use(res => { diff --git a/admin/src/utils/index.js b/admin/src/utils/index.js index 1e2a6a57..7d3ee160 100644 --- a/admin/src/utils/index.js +++ b/admin/src/utils/index.js @@ -47,4 +47,6 @@ export const pathMap = { 'agent-allow-form': 'Agent allow form', 'user': 'User', 'user-form': 'User form', + 'exam': 'Exam', + 'exam-form': 'Exam form', } diff --git a/admin/src/views/exam/form.vue b/admin/src/views/exam/form.vue index c23cd512..d9079124 100644 --- a/admin/src/views/exam/form.vue +++ b/admin/src/views/exam/form.vue @@ -1,3 +1,239 @@ + + + + diff --git a/admin/src/views/exam/index.vue b/admin/src/views/exam/index.vue index 4702895f..945401a3 100644 --- a/admin/src/views/exam/index.vue +++ b/admin/src/views/exam/index.vue @@ -1,3 +1,162 @@ + + + + diff --git a/admin/src/views/login.vue b/admin/src/views/login.vue index d869c6e7..145156e8 100644 --- a/admin/src/views/login.vue +++ b/admin/src/views/login.vue @@ -29,10 +29,14 @@ import axios from '../utils/axios' import { reactive, ref, toRefs } from 'vue' import { localSet } from '../utils' +import api from '../utils/api' +import { useRouter, useRoute } from 'vue-router' + export default { name: 'Login', setup() { const loginForm = ref(null) + const router = useRouter() const state = reactive({ ruleForm: { username: '', @@ -51,12 +55,9 @@ export default { const submitForm = async () => { loginForm.value.validate((valid) => { if (valid) { - axios.post('/adminUser/login', { - userName: state.ruleForm.username || '', - passwordMd5: md5(state.ruleForm.password) - }).then(res => { - localSet('token', res) - window.location.href = '/' + api.login(state.ruleForm).then(res => { + localSet('token', res.data.token) + router.push({name: 'dashboard'}) }) } else { console.log('error submit!!') diff --git a/app/Exceptions/Handler.php b/app/Exceptions/Handler.php index 9677ff8d..9805e14a 100644 --- a/app/Exceptions/Handler.php +++ b/app/Exceptions/Handler.php @@ -7,6 +7,7 @@ use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler; use Illuminate\Http\JsonResponse; use Illuminate\Support\Arr; use Illuminate\Validation\ValidationException; +use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; use Throwable; class Handler extends ExceptionHandler @@ -51,6 +52,10 @@ class Handler extends ExceptionHandler $msg = Arr::first(Arr::first($errors)); return response()->json(fail($msg, $errors)); }); + + $this->renderable(function (NotFoundHttpException $e) { + return response()->json(fail('No query result.', request()->all()), 404); + }); } /** @@ -62,8 +67,15 @@ class Handler extends ExceptionHandler */ protected function prepareJsonResponse($request, Throwable $e) { + $data = $request->all(); + if (config('app.debug')) { + $msg = $e->getMessage() ?: get_class($e); + $data['trace'] = $e->getTraceAsString(); + } else { + $msg = 'Server Error'; + } return new JsonResponse( - fail(config('app.debug') ? ($e->getMessage() ?: get_class($e)) : 'Server Error', []), + fail($msg, $data), $this->isHttpException($e) ? $e->getStatusCode() : 500, $this->isHttpException($e) ? $e->getHeaders() : [], JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES diff --git a/app/Http/Controllers/AuthenticateController.php b/app/Http/Controllers/AuthenticateController.php new file mode 100644 index 00000000..abbf9e73 --- /dev/null +++ b/app/Http/Controllers/AuthenticateController.php @@ -0,0 +1,38 @@ +repository = $repository; + } + + public function login(Request $request) + { + $request->validate([ + 'username' => 'required', + 'password' => 'required', + ]); + $result = $this->repository->login($request->username, $request->password); + return $this->success($result); + } + + public function logout(Request $request) + { + $result = $this->repository->logout(Auth::id()); + return $this->success($result); + } + + +} diff --git a/app/Http/Controllers/UserController.php b/app/Http/Controllers/UserController.php index 0f979246..85a71b57 100644 --- a/app/Http/Controllers/UserController.php +++ b/app/Http/Controllers/UserController.php @@ -5,6 +5,7 @@ namespace App\Http\Controllers; use App\Http\Resources\UserResource; use App\Repositories\UserRepository; use Illuminate\Http\Request; +use Illuminate\Support\Facades\Auth; class UserController extends Controller { @@ -100,4 +101,12 @@ class UserController extends Controller $result = $this->repository->listClass(); return $this->success($result); } + + public function base() + { + $id = Auth::id(); + $result = $this->repository->getBase($id); + $resource = new UserResource($result); + return $this->success($resource); + } } diff --git a/app/Models/User.php b/app/Models/User.php index 6256811c..a8f8fcab 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -85,8 +85,7 @@ class User extends Authenticatable * @var array */ protected $hidden = [ - 'password', - 'remember_token', + 'secret', 'passhash', ]; /** diff --git a/app/Repositories/AuthenticateRepository.php b/app/Repositories/AuthenticateRepository.php index dbcdf789..5b0e59c0 100644 --- a/app/Repositories/AuthenticateRepository.php +++ b/app/Repositories/AuthenticateRepository.php @@ -1,7 +1,33 @@ where('username', $username) + ->firstOrFail(['id', 'secret', 'passhash']); + if (md5($user->secret . $password . $user->secret) != $user->passhash) { + throw new \InvalidArgumentException('username or password invalid'); + } + $token = DB::transaction(function () use ($user) { + $user->tokens()->delete(); + $tokenResult = $user->createToken(__CLASS__ . __FUNCTION__ . __LINE__); + return $tokenResult->plainTextToken; + }); + $result = $user->toArray(); + $result['token'] = $token; + return $result; + } + public function logout($id) + { + $user = User::query()->findOrFail($id, ['id']); + $result = $user->tokens()->delete(); + return $result; + } } diff --git a/app/Repositories/UserRepository.php b/app/Repositories/UserRepository.php index 8f1a0868..4d827f7c 100644 --- a/app/Repositories/UserRepository.php +++ b/app/Repositories/UserRepository.php @@ -14,6 +14,12 @@ class UserRepository extends BaseRepository return $query->paginate(); } + public function getBase($id) + { + $user = User::query()->findOrFail($id, ['id', 'username', 'email', 'avatar']); + return $user; + } + public function store(array $params) { $password = $params['password']; diff --git a/routes/api.php b/routes/api.php index 086777bc..9fe07975 100644 --- a/routes/api.php +++ b/routes/api.php @@ -14,10 +14,15 @@ use Illuminate\Support\Facades\Route; | */ -Route::group([], function () { +Route::group(['middleware' => ['auth:sanctum']], function () { + Route::post('logout', [\App\Http\Controllers\AuthenticateController::class, 'logout']); Route::resource('agent-allow', \App\Http\Controllers\AgentAllowController::class); Route::resource('user', \App\Http\Controllers\UserController::class); + Route::get('user-base', [\App\Http\Controllers\UserController::class, 'base']); Route::resource('exam', \App\Http\Controllers\ExamController::class); Route::get('exam-index', [\App\Http\Controllers\ExamController::class, 'indexes']); Route::get('class', [\App\Http\Controllers\UserController::class, 'classes']); }); + +Route::post('login', [\App\Http\Controllers\AuthenticateController::class, 'login']); +