diff --git a/.env.development b/.env.development index 37f0871ec..8e0d86f9f 100644 --- a/.env.development +++ b/.env.development @@ -1,2 +1,2 @@ -VITE_APP_BASE_API=/api +VITE_APP_BASE_API=http://localhost:5000 VITE_APP_HOMEPAGE=/dashboard/workbench diff --git a/.eslintrc.cjs b/.eslintrc.cjs index d5ef0743a..fbcaedb27 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -60,6 +60,7 @@ module.exports = { 'no-param-reassign': 'off', 'space-before-function-paren': 'off', 'class-methods-use-this': 'off', + 'consistent-return': 'off', 'jsx-a11y/click-events-have-key-events': 'off', 'jsx-a11y/interactive-supports-focus': 'off', diff --git a/.firebaserc b/.firebaserc new file mode 100644 index 000000000..65d5d8286 --- /dev/null +++ b/.firebaserc @@ -0,0 +1,5 @@ +{ + "projects": { + "default": "skillrazr-admin" + } +} diff --git a/.vscode/settings.json b/.vscode/settings.json index b18b0f3dd..e81a5fcd6 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -23,5 +23,5 @@ "i18n-ally.keystyle": "flat", "i18n-ally.sortKeys": true, "i18n-ally.sourceLanguage": "en_US", - "i18n-ally.displayLanguage": "zh_CN", + "i18n-ally.displayLanguage": "en_US", } diff --git a/README.md b/README.md index 8912ec31f..403967b4b 100644 --- a/README.md +++ b/README.md @@ -2,20 +2,12 @@

-

Slash Admin

+

SkillRazr Admin App

- Slash Admin is a modern admin dashboard template built with React 18, Vite, Ant Design, and TypeScript. It is designed to help developers quickly create powerful admin management systems. + SkillRazr Admin is a modern admin dashboard template built with React 18, Vite, Ant Design, and TypeScript. It is designed to help developers quickly create powerful admin management systems.

-**English** | [中文](./README.zh-CN.md) - -## Sponsor -
- - -
- ## Preview + https://admin.slashspaces.com/ diff --git a/README.zh-CN.md b/README.zh-CN.md deleted file mode 100644 index 707b4c0d6..000000000 --- a/README.zh-CN.md +++ /dev/null @@ -1,124 +0,0 @@ -
-
-
- -

Slash Admin

- - Slash Admin 是一款现代化的后台管理模板,基于 React 18、Vite、Ant Design 和 TypeScript 构建。它旨在帮助开发人员快速搭建功能强大的后台管理系统。 - - -
- -**中文** | [English](./README.md) - -## 赞助 -
- - -
- - -## 预览 -+ https://admin.slashspaces.com/ - -|![login.png](https://d3george.github.io/github-static/slash-admin/login.jpeg)|![login_dark.png](https://d3george.github.io/github-static/slash-admin/login_dark.jpeg) -| ----------------------------------------------------------------- | ------------------------------------------------------------------- | -|![analysis.png](https://d3george.github.io/github-static/slash-admin/analysis.png)|![workbench.png](https://d3george.github.io/github-static/slash-admin/workbench.png) -## 特性 - -- 使用 React 18 hooks 进行构建。 -- 基于 Vite 进行快速开发和热模块替换。 -- 集成 Ant Design,提供丰富的 UI 组件和设计模式。 -- 使用 TypeScript 编写,提供类型安全性和更好的开发体验。 -- 响应式设计,适应各种屏幕尺寸和设备。 -- 灵活的路由配置,支持多级嵌套路由。 -- 集成权限管理,根据用户角色控制页面访问权限。 -- 集成国际化支持,轻松切换多语言。 -- 集成常见的后台管理功能,如用户管理、角色管理、权限管理等。 -- 可定制的主题和样式,以满足您的品牌需求。 -- 基于 MSW 和 Faker.js 的Mock方案 -- 使用 Zustand 进行状态管理 -- 使用 React-Query 进行数据获取 - -## 文档 -[文档地址](https://docs-admin.slashspaces.com/) - -## 快速开始 - -### 获取项目代码 - -```bash -git clone https://github.com/d3george/slash-admin.git -``` - -### 安装依赖 - -在项目根目录下运行以下命令安装项目依赖: - -```bash -pnpm install -``` - -### 启动开发服务器 - -运行以下命令以启动开发服务器: - -```bash -pnpm dev -``` - -访问 [http://localhost:3001](http://localhost:3001) 查看您的应用程序。 - -### 构建生产版本 - -运行以下命令以构建生产版本: - -```bash -pnpm build -``` - -构建后的文件将位于 `dist` 目录中。 - -## 容器化部署 - -### 构建镜像并运行容器 -#### 构建镜像 -在终端中进入项目根目录,并执行以下命令来构建 Docker 镜像: -``` -docker build -t your-image-name . -``` -确保将 `your-image-name` 替换为你自己的镜像名称 - -#### 运行容器 -使用以下命令在 Docker 容器中运行你的应用: -``` -docker run -p 3001:80 your-image-name -``` -这将在容器的端口 `80` (暴露在`Dockerfile`中) 上运行你的应用,并将其映射到你主机的端口 `3001` 上。 - -现在,你可以通过访问 http://localhost:3001 来查看部署的应用。 - - -### 使用docker-compose.yaml -在终端中进入项目根目录,并执行以下命令来启动 Docker Compose: -``` -docker-compose up -d -``` -Docker Compose 根据`docker-compose.yaml`定义的配置构建镜像并在后台运行容器. - -容器运行成功后,同样可以通过访问 http://localhost:3001来查看部署的应用。 - -参考[.commitlint.config.js](./commitlint.config.js) - -- `feat` 新功能 -- `fix` 修复bug -- `docs` 文档注释 -- `style` 代码格式(不影响代码运行的变动) -- `refactor` 重构 -- `perf` 性能优化 -- `revert` 回滚commit -- `test` 测试相关 -- `chore` 构建过程或辅助工具的变动 -- `ci` 修改CI配置、脚本 -- `types` 类型定义文件修改 -- `wip` 开发中 diff --git a/firebase.json b/firebase.json new file mode 100644 index 000000000..6564edd5c --- /dev/null +++ b/firebase.json @@ -0,0 +1,12 @@ +{ + "hosting": { + "public": "dist", + "ignore": ["firebase.json", "**/.*", "**/node_modules/**"], + "rewrites": [ + { + "source": "**", + "destination": "/index.html" + } + ] + } +} diff --git a/index.html b/index.html index aca743b1f..7188c0e8b 100644 --- a/index.html +++ b/index.html @@ -3,7 +3,7 @@ - Slash Admin + SkillRazr Admin diff --git a/package-lock.json b/package-lock.json index a52879782..a38c47d5b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -27,13 +27,18 @@ "apexcharts": "^3.43.0", "autosuggest-highlight": "^3.3.4", "axios": "^1.5.1", + "bcryptjs": "^2.4.3", + "body-parser": "^1.20.2", "classnames": "^2.3.2", "color": "^4.2.3", + "cors": "^2.8.5", "dayjs": "^1.11.10", + "express": "^4.19.2", "framer-motion": "^10.16.4", "highlight.js": "^11.9.0", "i18next": "^23.5.1", "i18next-browser-languagedetector": "^7.1.0", + "jsonwebtoken": "^9.0.2", "nprogress": "^0.2.0", "numeral": "^2.0.6", "ramda": "^0.29.1", @@ -65,7 +70,12 @@ "@commitlint/config-conventional": "^17.7.0", "@faker-js/faker": "^8.1.0", "@types/autosuggest-highlight": "^3.2.0", + "@types/bcryptjs": "^2.4.6", + "@types/body-parser": "^1.19.5", "@types/color": "^3.0.4", + "@types/cors": "^2.8.17", + "@types/express": "^4.17.21", + "@types/jsonwebtoken": "^9.0.6", "@types/nprogress": "^0.2.1", "@types/numeral": "^2.0.3", "@types/ramda": "^0.29.6", @@ -2568,6 +2578,22 @@ "@babel/types": "^7.20.7" } }, + "node_modules/@types/bcryptjs": { + "version": "2.4.6", + "resolved": "https://registry.npmjs.org/@types/bcryptjs/-/bcryptjs-2.4.6.tgz", + "integrity": "sha512-9xlo6R2qDs5uixm0bcIqCeMCE6HiQsIyel9KQySStiyqNl2tnj2mP3DX1Nf56MD6KMenNNlBBsy3LJ7gUEQPXQ==", + "dev": true + }, + "node_modules/@types/body-parser": { + "version": "1.19.5", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", + "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==", + "dev": true, + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, "node_modules/@types/color": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/@types/color/-/color-3.0.6.tgz", @@ -2592,12 +2618,30 @@ "integrity": "sha512-hulKeREDdLFesGQjl96+4aoJSHY5b2GRjagzzcqCfIrWhe5vkCqIvrLbqzBaI1q94Vg8DNJZZqTR5ocdWmWclg==", "dev": true }, + "node_modules/@types/connect": { + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", + "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/cookie": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.6.0.tgz", "integrity": "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==", "dev": true }, + "node_modules/@types/cors": { + "version": "2.8.17", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.17.tgz", + "integrity": "sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/debug": { "version": "4.1.12", "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", @@ -2612,6 +2656,30 @@ "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", "dev": true }, + "node_modules/@types/express": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", + "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==", + "dev": true, + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.33", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "4.19.2", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.2.tgz", + "integrity": "sha512-dPSEQElyVJ97BuGduAqQjpBocZWAs0GR94z+ptL7JXQJeJdHw2WBG3EWdFrK36b8Q6j8P4cXOMhgUoi0IIfIsg==", + "dev": true, + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, "node_modules/@types/glob": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz", @@ -2645,6 +2713,12 @@ "hoist-non-react-statics": "^3.3.0" } }, + "node_modules/@types/http-errors": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", + "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==", + "dev": true + }, "node_modules/@types/js-cookie": { "version": "2.2.7", "resolved": "https://registry.npmjs.org/@types/js-cookie/-/js-cookie-2.2.7.tgz", @@ -2662,6 +2736,15 @@ "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", "dev": true }, + "node_modules/@types/jsonwebtoken": { + "version": "9.0.6", + "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.6.tgz", + "integrity": "sha512-/5hndP5dCjloafCXns6SZyESp3Ldq7YjH3zwzwczYnjxIT0Fqzk5ROSYVGfFyczIue7IUEj8hkvLbPoLQ18vQw==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/lodash": { "version": "4.17.1", "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.1.tgz", @@ -2683,6 +2766,12 @@ "@types/unist": "^2" } }, + "node_modules/@types/mime": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", + "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", + "dev": true + }, "node_modules/@types/minimatch": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz", @@ -2751,6 +2840,12 @@ "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz", "integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==" }, + "node_modules/@types/qs": { + "version": "6.9.15", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.15.tgz", + "integrity": "sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg==", + "dev": true + }, "node_modules/@types/quill": { "version": "1.3.10", "resolved": "https://registry.npmjs.org/@types/quill/-/quill-1.3.10.tgz", @@ -2768,6 +2863,12 @@ "types-ramda": "^0.29.10" } }, + "node_modules/@types/range-parser": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", + "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", + "dev": true + }, "node_modules/@types/react": { "version": "18.3.2", "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.2.tgz", @@ -2833,6 +2934,27 @@ "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==", "dev": true }, + "node_modules/@types/send": { + "version": "0.17.4", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", + "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", + "dev": true, + "dependencies": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "node_modules/@types/serve-static": { + "version": "1.15.7", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.7.tgz", + "integrity": "sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==", + "dev": true, + "dependencies": { + "@types/http-errors": "*", + "@types/node": "*", + "@types/send": "*" + } + }, "node_modules/@types/statuses": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/@types/statuses/-/statuses-2.0.5.tgz", @@ -3246,6 +3368,18 @@ "resolved": "https://registry.npmjs.org/@yr/monotone-cubic-spline/-/monotone-cubic-spline-1.0.3.tgz", "integrity": "sha512-FQXkOta0XBSUPHndIKON2Y9JeQz5ZeMqLYZVVK93FliNBFm7LNMIZmY6FrMEB9XPcDbE2bekMbZD6kzDkxwYjA==" }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/acorn": { "version": "8.11.3", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", @@ -3500,6 +3634,11 @@ "node": ">=0.10.0" } }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" + }, "node_modules/array-ify": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/array-ify/-/array-ify-1.0.0.tgz", @@ -3924,6 +4063,11 @@ "node": ">=0.10.0" } }, + "node_modules/bcryptjs": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz", + "integrity": "sha512-V/Hy/X9Vt7f3BbPJEi8BdVFMByHi+jNXrYkW3huaybV/kQ0KJg0Y6PkEMbn+zeT+i+SiKZ/HMqJGIIt4LZDqNQ==" + }, "node_modules/big.js": { "version": "5.2.2", "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", @@ -3951,6 +4095,42 @@ "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", "dev": true }, + "node_modules/body-parser": { + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", + "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/body-parser/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/body-parser/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, "node_modules/boolbase": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", @@ -4010,12 +4190,25 @@ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, + "node_modules/buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" + }, "node_modules/buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "devOptional": true }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/cac": { "version": "6.7.14", "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", @@ -4646,6 +4839,25 @@ "integrity": "sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA==", "dev": true }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/conventional-changelog-angular": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-6.0.0.tgz", @@ -4702,6 +4914,11 @@ "node": ">= 0.6" } }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" + }, "node_modules/copy-anything": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-3.0.5.tgz", @@ -4737,7 +4954,6 @@ "version": "2.8.5", "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", - "dev": true, "dependencies": { "object-assign": "^4", "vary": "^1" @@ -5253,6 +5469,14 @@ "node": ">=0.4.0" } }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/dequal": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", @@ -5261,6 +5485,15 @@ "node": ">=6" } }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, "node_modules/didyoumean": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", @@ -5389,6 +5622,19 @@ "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", "dev": true }, + "node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" + }, "node_modules/electron-to-chromium": { "version": "1.4.763", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.763.tgz", @@ -5409,6 +5655,14 @@ "node": ">= 4" } }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/entities": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", @@ -5631,6 +5885,11 @@ "node": ">=6" } }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + }, "node_modules/escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", @@ -6239,7 +6498,6 @@ "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", - "dev": true, "engines": { "node": ">= 0.6" } @@ -6364,6 +6622,73 @@ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "dev": true }, + "node_modules/express": { + "version": "4.19.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", + "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.2", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.6.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.2.0", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.7", + "qs": "6.11.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.18.0", + "serve-static": "1.15.0", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/express/node_modules/cookie": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/express/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/express/node_modules/path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" + }, "node_modules/extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", @@ -6554,6 +6879,36 @@ "node": ">=8" } }, + "node_modules/finalhandler": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/finalhandler/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/finalhandler/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, "node_modules/find-root": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", @@ -6681,6 +7036,14 @@ "node": ">=0.4.x" } }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/fraction.js": { "version": "4.3.7", "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", @@ -6729,6 +7092,14 @@ } } }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/fs-extra": { "version": "11.2.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", @@ -7507,6 +7878,21 @@ "readable-stream": "^3.1.1" } }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/human-signals": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", @@ -7566,6 +7952,17 @@ "@babel/runtime": "^7.23.2" } }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/ignore": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", @@ -7662,8 +8059,7 @@ "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, "node_modules/ini": { "version": "1.3.8", @@ -7707,6 +8103,14 @@ "loose-envify": "^1.0.0" } }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "engines": { + "node": ">= 0.10" + } + }, "node_modules/is-accessor-descriptor": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.1.tgz", @@ -8584,6 +8988,27 @@ "node": "*" } }, + "node_modules/jsonwebtoken": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", + "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==", + "dependencies": { + "jws": "^3.2.2", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=12", + "npm": ">=6" + } + }, "node_modules/jsx-ast-utils": { "version": "3.3.5", "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", @@ -8599,6 +9024,25 @@ "node": ">=4.0" } }, + "node_modules/jwa": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", + "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", + "dependencies": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jws": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "dependencies": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", @@ -8969,17 +9413,41 @@ "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", "dev": true }, + "node_modules/lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==" + }, + "node_modules/lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==" + }, "node_modules/lodash.isfunction": { "version": "3.0.9", "resolved": "https://registry.npmjs.org/lodash.isfunction/-/lodash.isfunction-3.0.9.tgz", "integrity": "sha512-AirXNj15uRIMMPihnkInB4i3NHeb4iBtNg9WRWuK2o31S+ePwwNmDPaTL3o7dTJ+VXNZim7rFs4rxN4YU1oUJw==", "dev": true }, + "node_modules/lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==" + }, + "node_modules/lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==" + }, "node_modules/lodash.isplainobject": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", - "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", - "dev": true + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==" + }, + "node_modules/lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==" }, "node_modules/lodash.kebabcase": { "version": "4.1.1", @@ -8999,6 +9467,11 @@ "integrity": "sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==", "dev": true }, + "node_modules/lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==" + }, "node_modules/lodash.snakecase": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz", @@ -9563,6 +10036,14 @@ "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==" }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/memoize-one": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz", @@ -9605,6 +10086,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" + }, "node_modules/merge-options": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-options/-/merge-options-1.0.1.tgz", @@ -9632,6 +10118,14 @@ "node": ">= 8" } }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/micromark": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/micromark/-/micromark-3.2.0.tgz", @@ -10180,6 +10674,17 @@ "node": ">=8.6" } }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/mime-db": { "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", @@ -10462,6 +10967,14 @@ "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", "dev": true }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/node-releases": { "version": "2.0.14", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", @@ -10627,7 +11140,6 @@ "version": "1.13.1", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", - "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -10795,6 +11307,17 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -10960,6 +11483,14 @@ "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==" }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/pascalcase": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", @@ -11903,6 +12434,18 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, "node_modules/proxy-from-env": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", @@ -11925,6 +12468,20 @@ "react": "^16.8.0 || ^17.0.0 || ^18.0.0" } }, + "node_modules/qs": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/query-string": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/query-string/-/query-string-4.3.4.tgz", @@ -12017,6 +12574,28 @@ "url": "https://opencollective.com/ramda" } }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/rc-cascader": { "version": "3.25.0", "resolved": "https://registry.npmjs.org/rc-cascader/-/rc-cascader-3.25.0.tgz", @@ -13642,7 +14221,6 @@ "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, "funding": [ { "type": "github", @@ -13684,6 +14262,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, "node_modules/sass": { "version": "1.77.1", "resolved": "https://registry.npmjs.org/sass/-/sass-1.77.1.tgz", @@ -13732,7 +14315,6 @@ "version": "7.5.4", "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "dev": true, "dependencies": { "lru-cache": "^6.0.0" }, @@ -13747,7 +14329,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, "dependencies": { "yallist": "^4.0.0" }, @@ -13758,8 +14339,62 @@ "node_modules/semver/node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/send": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/send/node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/serve-static": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.18.0" + }, + "engines": { + "node": ">= 0.8.0" + } }, "node_modules/server-only": { "version": "0.0.1", @@ -13861,6 +14496,11 @@ "node": ">=0.10.0" } }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, "node_modules/shallowequal": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz", @@ -13891,7 +14531,6 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", - "dev": true, "dependencies": { "call-bind": "^1.0.7", "es-errors": "^1.3.0", @@ -14372,7 +15011,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "dev": true, "engines": { "node": ">= 0.8" } @@ -16978,6 +17616,14 @@ "resolved": "https://registry.npmjs.org/toggle-selection/-/toggle-selection-1.0.6.tgz", "integrity": "sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ==" }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "engines": { + "node": ">=0.6" + } + }, "node_modules/traverse": { "version": "0.6.9", "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.6.9.tgz", @@ -17208,6 +17854,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/typed-array-buffer": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", @@ -17573,6 +18231,14 @@ "node": ">= 10.0.0" } }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/unset-value": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", @@ -17712,6 +18378,14 @@ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", "dev": true }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "engines": { + "node": ">= 0.4.0" + } + }, "node_modules/uvu": { "version": "0.5.6", "resolved": "https://registry.npmjs.org/uvu/-/uvu-0.5.6.tgz", @@ -17757,7 +18431,6 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", - "dev": true, "engines": { "node": ">= 0.8" } diff --git a/package.json b/package.json index b2c118f2c..0de1b3394 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,8 @@ "build": "tsc && vite build", "lint": "eslint src --ext ts,tsx --report-unused-disable-directives --max-warnings 0", "preview": "vite preview", - "prepare": "husky install" + "prepare": "husky install", + "startServer": "npx ts-node src/server.ts" }, "dependencies": { "@ant-design/cssinjs": "^1.17.2", @@ -31,13 +32,18 @@ "apexcharts": "^3.43.0", "autosuggest-highlight": "^3.3.4", "axios": "^1.5.1", + "bcryptjs": "^2.4.3", + "body-parser": "^1.20.2", "classnames": "^2.3.2", "color": "^4.2.3", + "cors": "^2.8.5", "dayjs": "^1.11.10", + "express": "^4.19.2", "framer-motion": "^10.16.4", "highlight.js": "^11.9.0", "i18next": "^23.5.1", "i18next-browser-languagedetector": "^7.1.0", + "jsonwebtoken": "^9.0.2", "nprogress": "^0.2.0", "numeral": "^2.0.6", "ramda": "^0.29.1", @@ -69,7 +75,12 @@ "@commitlint/config-conventional": "^17.7.0", "@faker-js/faker": "^8.1.0", "@types/autosuggest-highlight": "^3.2.0", + "@types/bcryptjs": "^2.4.6", + "@types/body-parser": "^1.19.5", "@types/color": "^3.0.4", + "@types/cors": "^2.8.17", + "@types/express": "^4.17.21", + "@types/jsonwebtoken": "^9.0.6", "@types/nprogress": "^0.2.1", "@types/numeral": "^2.0.3", "@types/ramda": "^0.29.6", diff --git a/src/App.tsx b/src/App.tsx index 66a4609f0..be5fa947b 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -13,7 +13,7 @@ function App() { - Slash Admin + SkillRazr Admin diff --git a/src/_mock/assets.js b/src/_mock/assets.js index 68de9a390..4e6e34baa 100644 --- a/src/_mock/assets.js +++ b/src/_mock/assets.js @@ -531,3 +531,5 @@ export const TEST_USER = { permissions: TEST_ROLE.permission, }; export const USER_LIST = [DEFAULT_USER, TEST_USER]; +export const adminPermissions = ADMIN_ROLE.permission; +export const testPermmissions = TEST_ROLE.permission; diff --git a/src/_mock/handlers/_user.js b/src/_mock/handlers/_user.js index 6ce6ab4e6..cd2c4ce16 100644 --- a/src/_mock/handlers/_user.js +++ b/src/_mock/handlers/_user.js @@ -5,9 +5,9 @@ import { UserApi } from '@/api/services/userService'; import { USER_LIST } from '../assets'; +// mock server - this is not used as Node server is used const signIn = http.post(`/api${UserApi.SignIn}`, async ({ request }) => { const { username, password } = await request.json(); - const user = USER_LIST.find((item) => item.username === username); if (!user || user.password !== password) { diff --git a/src/api/apiClient.ts b/src/api/apiClient.ts index f31946f9b..d53edf216 100644 --- a/src/api/apiClient.ts +++ b/src/api/apiClient.ts @@ -7,14 +7,13 @@ import { t } from '@/locales/i18n'; import { Result } from '#/api'; import { ResultEnum } from '#/enum'; -// 创建 axios 实例 +console.log('api base url', import.meta.env.VITE_APP_BASE_API); const axiosInstance = axios.create({ baseURL: import.meta.env.VITE_APP_BASE_API, timeout: 50000, headers: { 'Content-Type': 'application/json;charset=utf-8' }, }); -// 请求拦截 axiosInstance.interceptors.request.use( (config) => { // 在请求被发送之前做些什么 @@ -30,11 +29,14 @@ axiosInstance.interceptors.request.use( // 响应拦截 axiosInstance.interceptors.response.use( (res: AxiosResponse) => { + console.log('axios resp1', res); + if (!res.data) throw new Error(t('sys.api.apiRequestFailed')); const { status, data, message } = res.data; - // 业务请求成功 + const hasSuccess = data && Reflect.has(res.data, 'status') && status === ResultEnum.SUCCESS; + if (hasSuccess) { return data; } @@ -50,7 +52,6 @@ axiosInstance.interceptors.response.use( } catch (error) { throw new Error(error as unknown as string); } - // 对响应错误做点什么 if (isEmpty(errMsg)) { // checkStatus // errMsg = checkStatus(response.data.status); diff --git a/src/api/services/userService.ts b/src/api/services/userService.ts index 59a037b08..dc74d5070 100644 --- a/src/api/services/userService.ts +++ b/src/api/services/userService.ts @@ -13,11 +13,11 @@ export interface SignUpReq extends SignInReq { export type SignInRes = UserToken & { user: UserInfo }; export enum UserApi { - SignIn = '/auth/signin', - SignUp = '/auth/signup', - Logout = '/auth/logout', - Refresh = '/auth/refresh', - User = '/user', + SignIn = 'signin', + SignUp = 'signup', + Logout = 'logout', + Refresh = 'refresh', + User = 'user', } const signin = (data: SignInReq) => apiClient.post({ url: UserApi.SignIn, data }); diff --git a/src/assets/images/skillrazr.jpg b/src/assets/images/skillrazr.jpg new file mode 100644 index 000000000..839c83314 Binary files /dev/null and b/src/assets/images/skillrazr.jpg differ diff --git a/src/layouts/_common/notice.tsx b/src/layouts/_common/notice.tsx index fdc646d50..50ff9b2f6 100644 --- a/src/layouts/_common/notice.tsx +++ b/src/layouts/_common/notice.tsx @@ -128,7 +128,7 @@ function NoticeTab() {
{faker.person.fullName()} mentioned you in - Slash Admin + SkillRazr Admin
1 days ago
diff --git a/src/layouts/dashboard/nav.tsx b/src/layouts/dashboard/nav.tsx index 91416ff2e..260a6e368 100644 --- a/src/layouts/dashboard/nav.tsx +++ b/src/layouts/dashboard/nav.tsx @@ -131,7 +131,7 @@ export default function Nav(props: Props) { {themeLayout !== ThemeLayout.Mini && ( - Slash Admin + SkillRazr Admin )} diff --git a/src/pages/dashboard/workbench/banner-card.tsx b/src/pages/dashboard/workbench/banner-card.tsx index fe8c64c71..b0a4379d9 100644 --- a/src/pages/dashboard/workbench/banner-card.tsx +++ b/src/pages/dashboard/workbench/banner-card.tsx @@ -33,8 +33,8 @@ export default function BannerCard() { style={{ color: themeToken.colorPrimaryTextActive }} className="mx-auto mb-6 mt-4 max-w-sm text-sm opacity-80 md:mx-0" > - Welcome to join the Discord channel to discuss everything about Slash Admin, or you can - visite my blog: + Welcome to join the Discord channel to discuss everything about SkillRazr Admin, or you + can visite my blog:
new Date(expiresIn!).getTime(); + + if (accessToken && !isTokenExpired) { return ; } @@ -40,7 +40,9 @@ function Login() { background: bg, }} > -
Slash Admin
+
+ SkillRazr Admin +
{t('sys.login.signInSecondTitle')} diff --git a/src/pages/sys/login/LoginForm.tsx b/src/pages/sys/login/LoginForm.tsx index 914f9e49e..adff29ffe 100644 --- a/src/pages/sys/login/LoginForm.tsx +++ b/src/pages/sys/login/LoginForm.tsx @@ -1,12 +1,11 @@ -import { Alert, Button, Checkbox, Col, Divider, Form, Input, Row } from 'antd'; +import { Button, Checkbox, Col, Divider, Form, Input, Row } from 'antd'; import { useState } from 'react'; import { useTranslation } from 'react-i18next'; import { AiFillGithub, AiFillGoogleCircle, AiFillWechat } from 'react-icons/ai'; -import { DEFAULT_USER, TEST_USER } from '@/_mock/assets'; +import { DEFAULT_USER } from '@/_mock/assets'; import { SignInReq } from '@/api/services/userService'; import { useSignIn } from '@/store/userStore'; -import ProTag from '@/theme/antd/components/tag'; import { useThemeToken } from '@/theme/hooks'; import { LoginStateEnum, useLoginStateContext } from './providers/LoginStateProvider'; @@ -42,37 +41,6 @@ function LoginForm() { }} onFinish={handleFinish} > -
- -
- Admin {t('sys.login.userName')}: - - {DEFAULT_USER.username} - -
- -
- Test {t('sys.login.userName')}: - - {TEST_USER.username} - -
- -
- {t('sys.login.password')}: - - {DEFAULT_USER.password} - -
-
- } - showIcon - /> -
- { console.log('Received values of form: ', values); - await signUpMutation.mutateAsync(values); - backToLogin(); + try { + const resp = await signUpMutation.mutateAsync(values); + console.log('resp signup from server', resp); + backToLogin(); + } catch (e) { + console.log('e', e); + } }; return ( diff --git a/src/pages/sys/others/calendar/index.tsx b/src/pages/sys/others/calendar/index.tsx index b02d00460..d3a892974 100644 --- a/src/pages/sys/others/calendar/index.tsx +++ b/src/pages/sys/others/calendar/index.tsx @@ -28,7 +28,7 @@ const DefaultEventInitValue = { color: '', }; export default function Calendar() { - const [events, setEvents] = useState([]); + const [events] = useState([]); const fullCalendarRef = useRef(null); const [view, setView] = useState('dayGridMonth'); const [date, setDate] = useState(new Date()); diff --git a/src/router/components/auth-guard.tsx b/src/router/components/auth-guard.tsx index 2c0b88a36..0c8e56c43 100644 --- a/src/router/components/auth-guard.tsx +++ b/src/router/components/auth-guard.tsx @@ -11,13 +11,16 @@ type Props = { }; export default function AuthGuard({ children }: Props) { const router = useRouter(); - const { accessToken } = useUserToken(); + const { accessToken, expiresIn } = useUserToken(); + console.log('accessToken', accessToken, expiresIn); + const isTokenExpired = Date.now() > new Date(expiresIn!).getTime(); + console.log('token expired', isTokenExpired); const check = useCallback(() => { - if (!accessToken) { + if (!accessToken || isTokenExpired) { router.replace('/login'); } - }, [router, accessToken]); + }, [router, accessToken, isTokenExpired]); useEffect(() => { check(); diff --git a/src/server.ts b/src/server.ts new file mode 100644 index 000000000..ce1d4eacf --- /dev/null +++ b/src/server.ts @@ -0,0 +1,142 @@ +import bcrypt from 'bcryptjs'; +import bodyParser from 'body-parser'; +import cors from 'cors'; +import express, { Request, Response } from 'express'; +import jwt from 'jsonwebtoken'; + +import { adminPermissions } from './_mock/assets'; + +const app = express(); +const PORT = 5000; + +// Secret key for JWT +const JWT_SECRET = 'skillrazr_admin_app_1234$2893'; + +// Middleware +app.use(bodyParser.json()); +app.use(cors()); + +// Mock user data (replace this with your database in a real app) +interface User { + username: string; + password: string; + permissions: any; +} +const users: User[] = []; + +console.log('users in the server', users); +console.log('hello'); +// +// Signup endpoint +app.post('/signup', async (req: Request, res: Response): Promise => { + const { username, password } = req.body; + + console.log('signup, userName', 'password', username, password); + + // Check if the user already exists + const userExists = users.find((user) => user.username === username); + if (userExists) { + return res.status(400).json({ message: 'User already exists' }); + } + + // Hash the password + const hashedPassword = await bcrypt.hash(password, 10); + + // Save the new user + users.push({ username, password: hashedPassword, permissions: adminPermissions }); + + console.log('hashed password', hashedPassword, 'users database', users); + + return res.status(201).json({ message: 'User created successfully', status: 0, data: [] }); +}); + +// Signin endpoint +app.post('/signin', async (req: Request, res: Response) => { + const { username, password } = req.body; + + const now = Date.now(); + const expiresIn = new Date(now + 1 * 60 * 1000).toISOString(); + + console.log('sign in, userName', 'password', username, password, expiresIn); + + // Find the user + const user = users.find((user) => user.username === username); + + console.log('user found ', user); + if (!user) { + return res.status(400).json({ message: 'Invalid credentials' }); + } + + // Check the password + const isMatch = await bcrypt.compare(password, user.password); + if (!isMatch) { + return res.status(400).json({ message: 'Invalid credentials' }); + } + + // Generate a JWT token + const token = jwt.sign({ username: user.username }, JWT_SECRET, { expiresIn: '1h' }); + + res.json({ status: 0, data: { user, accessToken: token, expiresIn } }); +}); + +// Protected route example +app.get('/protected', (req: Request, res: Response) => { + const token = req.headers.authorization; + if (!token) { + return res.status(401).json({ message: 'You are not authorized to access this' }); + } + + jwt.verify(token, JWT_SECRET, (err, decoded) => { + if (err) { + return res.status(401).json({ message: 'Invalid token' }); + } + + res.json({ message: 'Protected route accessed', user: decoded, status: 0 }); + }); +}); + +// const tokenCheck = (req, res, next) => { +// const token = req.headers['authorization']; +// if (!token) { +// return res.status(401).json({ message: 'You are not authorized to access this'}); +// } else { +// // do token checks using jwt +// jwt.verify(token, JWT_SECRET, (err, decoded) => { +// if (err) { +// return res.status(401).json({ message: 'Invalid token' }); +// } + +// next() +// }); +// } +// } + +// app.get('/getExerciseMarks', [tokenCheck], (req: Request, res: Response) => { +// const {userName} = req; + +// // make a db call to get exercise scroes for this userName + +// const token = req.headers['authorization']; +// if (!token) { +// return res.status(401).json({ message: 'You are not authorized to access this' }); +// } +// // get exerciseScore from exerciseDb + +// }); + +// app.get('/getQuizScores', [tokenCheck], (req: Request, res: Response) => { +// const token = req.headers['authorization']; +// if (!token) { +// return res.status(401).json({ message: 'You are not authorized to access this' }); +// } + +// // get quizScore from exerciseDb +// }); + +app.get('/', (req: Request, res: Response) => { + res.send('Hello World!'); +}); + +app.listen(PORT, () => { + console.log(`Server running on port ${PORT}`); +}); diff --git a/src/store/userStore.ts b/src/store/userStore.ts index a7704a916..207d2a839 100644 --- a/src/store/userStore.ts +++ b/src/store/userStore.ts @@ -60,8 +60,10 @@ export const useSignIn = () => { const signIn = async (data: SignInReq) => { try { const res = await signInMutation.mutateAsync(data); - const { user, accessToken, refreshToken } = res; - setUserToken({ accessToken, refreshToken }); + console.log('res from login api', res); + + const { user, accessToken, refreshToken, expiresIn } = res; + setUserToken({ accessToken, refreshToken, expiresIn }); setUserInfo(user); navigatge(HOMEPAGE, { replace: true }); diff --git a/tsconfig.json b/tsconfig.json index 463b4122c..6f50da188 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -40,6 +40,10 @@ "#/*": ["types/*"] } }, + "ts-node": { + "esm": true, + "experimentalSpecifierResolution": "node" + }, "include": ["src", "test", "types/**/*.ts", "**.ts", "*.json", "**.*js"], "exclude": ["node_modules", "dist"], "references": [{ "path": "./tsconfig.node.json" }] diff --git a/types/entity.ts b/types/entity.ts index 724e8e834..bfc1b8cc5 100644 --- a/types/entity.ts +++ b/types/entity.ts @@ -3,6 +3,7 @@ import { BasicStatus, PermissionType } from './enum'; export interface UserToken { accessToken?: string; refreshToken?: string; + expiresIn?: string } export interface UserInfo {