feat: 添加飞书以及github登录
This commit is contained in:
parent
946be43558
commit
219afa0353
10
.env
10
.env
|
|
@ -3,4 +3,12 @@ SERVER_HOST='192.144.32.178'
|
||||||
SERVER_PORT=3306
|
SERVER_PORT=3306
|
||||||
SERVER_USER='root'
|
SERVER_USER='root'
|
||||||
PASSWORD='lichao1314'
|
PASSWORD='lichao1314'
|
||||||
DB_NAME='auth_db'
|
DB_NAME='auth_db'
|
||||||
|
|
||||||
|
GITHUB_CLIENT_ID=Ov23lihk723FlNAwlFg6
|
||||||
|
GITHUB_CLIENT_SECRET=b839f50bba1f006ffdd43fb73c5ae221a54e1e2e
|
||||||
|
GITHUB_CALLBACK_URL=http://localhost:3030/auth/github/callback
|
||||||
|
|
||||||
|
|
||||||
|
FEISHU_APP_ID=cli_a66a897f687a5013
|
||||||
|
FEISHU_APP_SECRET=s106GAbbCZk66OcHN69Rng5TaLK6fiH2
|
||||||
|
|
|
||||||
|
|
@ -29,12 +29,16 @@
|
||||||
"@nestjs/platform-express": "^10.0.0",
|
"@nestjs/platform-express": "^10.0.0",
|
||||||
"@nestjs/typeorm": "^10.0.2",
|
"@nestjs/typeorm": "^10.0.2",
|
||||||
"@types/bcrypt": "^5.0.2",
|
"@types/bcrypt": "^5.0.2",
|
||||||
|
"@types/passport-github2": "^1.2.9",
|
||||||
"@types/uuid": "^10.0.0",
|
"@types/uuid": "^10.0.0",
|
||||||
|
"axios": "^1.7.9",
|
||||||
"bcrypt": "^5.1.1",
|
"bcrypt": "^5.1.1",
|
||||||
"bcryptjs": "^2.4.3",
|
"bcryptjs": "^2.4.3",
|
||||||
|
"dotenv": "^16.4.7",
|
||||||
"install": "^0.13.0",
|
"install": "^0.13.0",
|
||||||
"mysql2": "^3.12.0",
|
"mysql2": "^3.12.0",
|
||||||
"passport": "^0.7.0",
|
"passport": "^0.7.0",
|
||||||
|
"passport-github2": "^0.1.12",
|
||||||
"passport-jwt": "^4.0.1",
|
"passport-jwt": "^4.0.1",
|
||||||
"passport-local": "^1.0.0",
|
"passport-local": "^1.0.0",
|
||||||
"reflect-metadata": "^0.1.13",
|
"reflect-metadata": "^0.1.13",
|
||||||
|
|
|
||||||
100
pnpm-lock.yaml
100
pnpm-lock.yaml
|
|
@ -16,13 +16,16 @@ specifiers:
|
||||||
'@types/express': ^4.17.17
|
'@types/express': ^4.17.17
|
||||||
'@types/jest': ^29.5.2
|
'@types/jest': ^29.5.2
|
||||||
'@types/node': ^20.3.1
|
'@types/node': ^20.3.1
|
||||||
|
'@types/passport-github2': ^1.2.9
|
||||||
'@types/passport-jwt': ^4.0.1
|
'@types/passport-jwt': ^4.0.1
|
||||||
'@types/supertest': ^6.0.0
|
'@types/supertest': ^6.0.0
|
||||||
'@types/uuid': ^10.0.0
|
'@types/uuid': ^10.0.0
|
||||||
'@typescript-eslint/eslint-plugin': ^6.0.0
|
'@typescript-eslint/eslint-plugin': ^6.0.0
|
||||||
'@typescript-eslint/parser': ^6.0.0
|
'@typescript-eslint/parser': ^6.0.0
|
||||||
|
axios: ^1.7.9
|
||||||
bcrypt: ^5.1.1
|
bcrypt: ^5.1.1
|
||||||
bcryptjs: ^2.4.3
|
bcryptjs: ^2.4.3
|
||||||
|
dotenv: ^16.4.7
|
||||||
eslint: ^8.42.0
|
eslint: ^8.42.0
|
||||||
eslint-config-prettier: ^9.0.0
|
eslint-config-prettier: ^9.0.0
|
||||||
eslint-plugin-prettier: ^5.0.0
|
eslint-plugin-prettier: ^5.0.0
|
||||||
|
|
@ -30,6 +33,7 @@ specifiers:
|
||||||
jest: ^29.5.0
|
jest: ^29.5.0
|
||||||
mysql2: ^3.12.0
|
mysql2: ^3.12.0
|
||||||
passport: ^0.7.0
|
passport: ^0.7.0
|
||||||
|
passport-github2: ^0.1.12
|
||||||
passport-jwt: ^4.0.1
|
passport-jwt: ^4.0.1
|
||||||
passport-local: ^1.0.0
|
passport-local: ^1.0.0
|
||||||
prettier: ^3.0.0
|
prettier: ^3.0.0
|
||||||
|
|
@ -55,12 +59,16 @@ dependencies:
|
||||||
'@nestjs/platform-express': 10.4.15_5u4hn6whjn5aawl2edmluzh4i4
|
'@nestjs/platform-express': 10.4.15_5u4hn6whjn5aawl2edmluzh4i4
|
||||||
'@nestjs/typeorm': 10.0.2_5ay6scu5luhdsc23ie3iqrw3sm
|
'@nestjs/typeorm': 10.0.2_5ay6scu5luhdsc23ie3iqrw3sm
|
||||||
'@types/bcrypt': 5.0.2
|
'@types/bcrypt': 5.0.2
|
||||||
|
'@types/passport-github2': 1.2.9
|
||||||
'@types/uuid': 10.0.0
|
'@types/uuid': 10.0.0
|
||||||
|
axios: 1.7.9
|
||||||
bcrypt: 5.1.1
|
bcrypt: 5.1.1
|
||||||
bcryptjs: 2.4.3
|
bcryptjs: 2.4.3
|
||||||
|
dotenv: 16.4.7
|
||||||
install: 0.13.0
|
install: 0.13.0
|
||||||
mysql2: 3.12.0
|
mysql2: 3.12.0
|
||||||
passport: 0.7.0
|
passport: 0.7.0
|
||||||
|
passport-github2: 0.1.12
|
||||||
passport-jwt: 4.0.1
|
passport-jwt: 4.0.1
|
||||||
passport-local: 1.0.0
|
passport-local: 1.0.0
|
||||||
reflect-metadata: 0.1.14
|
reflect-metadata: 0.1.14
|
||||||
|
|
@ -1210,13 +1218,11 @@ packages:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/connect': 3.4.38
|
'@types/connect': 3.4.38
|
||||||
'@types/node': 20.17.12
|
'@types/node': 20.17.12
|
||||||
dev: true
|
|
||||||
|
|
||||||
/@types/connect/3.4.38:
|
/@types/connect/3.4.38:
|
||||||
resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==}
|
resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==}
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/node': 20.17.12
|
'@types/node': 20.17.12
|
||||||
dev: true
|
|
||||||
|
|
||||||
/@types/cookiejar/2.1.5:
|
/@types/cookiejar/2.1.5:
|
||||||
resolution: {integrity: sha512-he+DHOWReW0nghN24E1WUqM0efK4kI9oTqDm6XmK8ZPe2djZ90BSNdGnIyCLzCPw7/pogPlGbzI2wHGGmi4O/Q==}
|
resolution: {integrity: sha512-he+DHOWReW0nghN24E1WUqM0efK4kI9oTqDm6XmK8ZPe2djZ90BSNdGnIyCLzCPw7/pogPlGbzI2wHGGmi4O/Q==}
|
||||||
|
|
@ -1247,7 +1253,6 @@ packages:
|
||||||
'@types/qs': 6.9.17
|
'@types/qs': 6.9.17
|
||||||
'@types/range-parser': 1.2.7
|
'@types/range-parser': 1.2.7
|
||||||
'@types/send': 0.17.4
|
'@types/send': 0.17.4
|
||||||
dev: true
|
|
||||||
|
|
||||||
/@types/express/4.17.21:
|
/@types/express/4.17.21:
|
||||||
resolution: {integrity: sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==}
|
resolution: {integrity: sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==}
|
||||||
|
|
@ -1256,7 +1261,6 @@ packages:
|
||||||
'@types/express-serve-static-core': 4.19.6
|
'@types/express-serve-static-core': 4.19.6
|
||||||
'@types/qs': 6.9.17
|
'@types/qs': 6.9.17
|
||||||
'@types/serve-static': 1.15.7
|
'@types/serve-static': 1.15.7
|
||||||
dev: true
|
|
||||||
|
|
||||||
/@types/graceful-fs/4.1.9:
|
/@types/graceful-fs/4.1.9:
|
||||||
resolution: {integrity: sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==}
|
resolution: {integrity: sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==}
|
||||||
|
|
@ -1266,7 +1270,6 @@ packages:
|
||||||
|
|
||||||
/@types/http-errors/2.0.4:
|
/@types/http-errors/2.0.4:
|
||||||
resolution: {integrity: sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==}
|
resolution: {integrity: sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==}
|
||||||
dev: true
|
|
||||||
|
|
||||||
/@types/istanbul-lib-coverage/2.0.6:
|
/@types/istanbul-lib-coverage/2.0.6:
|
||||||
resolution: {integrity: sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==}
|
resolution: {integrity: sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==}
|
||||||
|
|
@ -1306,13 +1309,26 @@ packages:
|
||||||
|
|
||||||
/@types/mime/1.3.5:
|
/@types/mime/1.3.5:
|
||||||
resolution: {integrity: sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==}
|
resolution: {integrity: sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==}
|
||||||
dev: true
|
|
||||||
|
|
||||||
/@types/node/20.17.12:
|
/@types/node/20.17.12:
|
||||||
resolution: {integrity: sha512-vo/wmBgMIiEA23A/knMfn/cf37VnuF52nZh5ZoW0GWt4e4sxNquibrMRJ7UQsA06+MBx9r/H1jsI9grYjQCQlw==}
|
resolution: {integrity: sha512-vo/wmBgMIiEA23A/knMfn/cf37VnuF52nZh5ZoW0GWt4e4sxNquibrMRJ7UQsA06+MBx9r/H1jsI9grYjQCQlw==}
|
||||||
dependencies:
|
dependencies:
|
||||||
undici-types: 6.19.8
|
undici-types: 6.19.8
|
||||||
|
|
||||||
|
/@types/oauth/0.9.6:
|
||||||
|
resolution: {integrity: sha512-H9TRCVKBNOhZZmyHLqFt9drPM9l+ShWiqqJijU1B8P3DX3ub84NjxDuy+Hjrz+fEca5Kwip3qPMKNyiLgNJtIA==}
|
||||||
|
dependencies:
|
||||||
|
'@types/node': 20.17.12
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@types/passport-github2/1.2.9:
|
||||||
|
resolution: {integrity: sha512-/nMfiPK2E6GKttwBzwj0Wjaot8eHrM57hnWxu52o6becr5/kXlH/4yE2v2rh234WGvSgEEzIII02Nc5oC5xEHA==}
|
||||||
|
dependencies:
|
||||||
|
'@types/express': 4.17.21
|
||||||
|
'@types/passport': 1.0.17
|
||||||
|
'@types/passport-oauth2': 1.4.17
|
||||||
|
dev: false
|
||||||
|
|
||||||
/@types/passport-jwt/4.0.1:
|
/@types/passport-jwt/4.0.1:
|
||||||
resolution: {integrity: sha512-Y0Ykz6nWP4jpxgEUYq8NoVZeCQPo1ZndJLfapI249g1jHChvRfZRO/LS3tqu26YgAS/laI1qx98sYGz0IalRXQ==}
|
resolution: {integrity: sha512-Y0Ykz6nWP4jpxgEUYq8NoVZeCQPo1ZndJLfapI249g1jHChvRfZRO/LS3tqu26YgAS/laI1qx98sYGz0IalRXQ==}
|
||||||
dependencies:
|
dependencies:
|
||||||
|
|
@ -1320,6 +1336,14 @@ packages:
|
||||||
'@types/passport-strategy': 0.2.38
|
'@types/passport-strategy': 0.2.38
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/@types/passport-oauth2/1.4.17:
|
||||||
|
resolution: {integrity: sha512-ODiAHvso6JcWJ6ZkHHroVp05EHGhqQN533PtFNBkg8Fy5mERDqsr030AX81M0D69ZcaMvhF92SRckEk2B0HYYg==}
|
||||||
|
dependencies:
|
||||||
|
'@types/express': 4.17.21
|
||||||
|
'@types/oauth': 0.9.6
|
||||||
|
'@types/passport': 1.0.17
|
||||||
|
dev: false
|
||||||
|
|
||||||
/@types/passport-strategy/0.2.38:
|
/@types/passport-strategy/0.2.38:
|
||||||
resolution: {integrity: sha512-GC6eMqqojOooq993Tmnmp7AUTbbQSgilyvpCYQjT+H6JfG/g6RGc7nXEniZlp0zyKJ0WUdOiZWLBZft9Yug1uA==}
|
resolution: {integrity: sha512-GC6eMqqojOooq993Tmnmp7AUTbbQSgilyvpCYQjT+H6JfG/g6RGc7nXEniZlp0zyKJ0WUdOiZWLBZft9Yug1uA==}
|
||||||
dependencies:
|
dependencies:
|
||||||
|
|
@ -1331,15 +1355,12 @@ packages:
|
||||||
resolution: {integrity: sha512-aciLyx+wDwT2t2/kJGJR2AEeBz0nJU4WuRX04Wu9Dqc5lSUtwu0WERPHYsLhF9PtseiAMPBGNUOtFjxZ56prsg==}
|
resolution: {integrity: sha512-aciLyx+wDwT2t2/kJGJR2AEeBz0nJU4WuRX04Wu9Dqc5lSUtwu0WERPHYsLhF9PtseiAMPBGNUOtFjxZ56prsg==}
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/express': 4.17.21
|
'@types/express': 4.17.21
|
||||||
dev: true
|
|
||||||
|
|
||||||
/@types/qs/6.9.17:
|
/@types/qs/6.9.17:
|
||||||
resolution: {integrity: sha512-rX4/bPcfmvxHDv0XjfJELTTr+iB+tn032nPILqHm5wbthUUUuVtNGGqzhya9XUxjTP8Fpr0qYgSZZKxGY++svQ==}
|
resolution: {integrity: sha512-rX4/bPcfmvxHDv0XjfJELTTr+iB+tn032nPILqHm5wbthUUUuVtNGGqzhya9XUxjTP8Fpr0qYgSZZKxGY++svQ==}
|
||||||
dev: true
|
|
||||||
|
|
||||||
/@types/range-parser/1.2.7:
|
/@types/range-parser/1.2.7:
|
||||||
resolution: {integrity: sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==}
|
resolution: {integrity: sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==}
|
||||||
dev: true
|
|
||||||
|
|
||||||
/@types/semver/7.5.8:
|
/@types/semver/7.5.8:
|
||||||
resolution: {integrity: sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==}
|
resolution: {integrity: sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==}
|
||||||
|
|
@ -1350,7 +1371,6 @@ packages:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/mime': 1.3.5
|
'@types/mime': 1.3.5
|
||||||
'@types/node': 20.17.12
|
'@types/node': 20.17.12
|
||||||
dev: true
|
|
||||||
|
|
||||||
/@types/serve-static/1.15.7:
|
/@types/serve-static/1.15.7:
|
||||||
resolution: {integrity: sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==}
|
resolution: {integrity: sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==}
|
||||||
|
|
@ -1358,7 +1378,6 @@ packages:
|
||||||
'@types/http-errors': 2.0.4
|
'@types/http-errors': 2.0.4
|
||||||
'@types/node': 20.17.12
|
'@types/node': 20.17.12
|
||||||
'@types/send': 0.17.4
|
'@types/send': 0.17.4
|
||||||
dev: true
|
|
||||||
|
|
||||||
/@types/stack-utils/2.0.3:
|
/@types/stack-utils/2.0.3:
|
||||||
resolution: {integrity: sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==}
|
resolution: {integrity: sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==}
|
||||||
|
|
@ -1839,13 +1858,22 @@ packages:
|
||||||
|
|
||||||
/asynckit/0.4.0:
|
/asynckit/0.4.0:
|
||||||
resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==}
|
resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==}
|
||||||
dev: true
|
|
||||||
|
|
||||||
/aws-ssl-profiles/1.1.2:
|
/aws-ssl-profiles/1.1.2:
|
||||||
resolution: {integrity: sha512-NZKeq9AfyQvEeNlN0zSYAaWrmBffJh3IELMZfRpJVWgrpEbtEpnjvzqBPf+mxoI287JohRDoa+/nsfqqiZmF6g==}
|
resolution: {integrity: sha512-NZKeq9AfyQvEeNlN0zSYAaWrmBffJh3IELMZfRpJVWgrpEbtEpnjvzqBPf+mxoI287JohRDoa+/nsfqqiZmF6g==}
|
||||||
engines: {node: '>= 6.0.0'}
|
engines: {node: '>= 6.0.0'}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/axios/1.7.9:
|
||||||
|
resolution: {integrity: sha512-LhLcE7Hbiryz8oMDdDptSrWowmB4Bl6RCt6sIJKpRB4XtVf0iEgewX3au/pJqm+Py1kCASkb/FFKjxQaLtxJvw==}
|
||||||
|
dependencies:
|
||||||
|
follow-redirects: 1.15.9
|
||||||
|
form-data: 4.0.1
|
||||||
|
proxy-from-env: 1.1.0
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- debug
|
||||||
|
dev: false
|
||||||
|
|
||||||
/babel-jest/29.7.0_@babel+core@7.26.0:
|
/babel-jest/29.7.0_@babel+core@7.26.0:
|
||||||
resolution: {integrity: sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==}
|
resolution: {integrity: sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==}
|
||||||
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
|
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
|
||||||
|
|
@ -1927,6 +1955,11 @@ packages:
|
||||||
/base64-js/1.5.1:
|
/base64-js/1.5.1:
|
||||||
resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
|
resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
|
||||||
|
|
||||||
|
/base64url/3.0.1:
|
||||||
|
resolution: {integrity: sha512-ir1UPr3dkwexU7FdV8qBBbNDRUhMmIekYMFZfi+C/sLNnRESKPl23nB9b2pltqfOQNnGzsDdId90AEtG5tCx4A==}
|
||||||
|
engines: {node: '>=6.0.0'}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/bcrypt/5.1.1:
|
/bcrypt/5.1.1:
|
||||||
resolution: {integrity: sha512-AGBHOG5hPYZ5Xl9KXzU5iKq9516yEmvCKDg3ecP5kX2aB6UqTeXZxk2ELnDgDm6BQSMlLt9rDB4LoSMx0rYwww==}
|
resolution: {integrity: sha512-AGBHOG5hPYZ5Xl9KXzU5iKq9516yEmvCKDg3ecP5kX2aB6UqTeXZxk2ELnDgDm6BQSMlLt9rDB4LoSMx0rYwww==}
|
||||||
engines: {node: '>= 10.0.0'}
|
engines: {node: '>= 10.0.0'}
|
||||||
|
|
@ -2239,7 +2272,6 @@ packages:
|
||||||
engines: {node: '>= 0.8'}
|
engines: {node: '>= 0.8'}
|
||||||
dependencies:
|
dependencies:
|
||||||
delayed-stream: 1.0.0
|
delayed-stream: 1.0.0
|
||||||
dev: true
|
|
||||||
|
|
||||||
/commander/2.20.3:
|
/commander/2.20.3:
|
||||||
resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==}
|
resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==}
|
||||||
|
|
@ -2426,7 +2458,6 @@ packages:
|
||||||
/delayed-stream/1.0.0:
|
/delayed-stream/1.0.0:
|
||||||
resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
|
resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
|
||||||
engines: {node: '>=0.4.0'}
|
engines: {node: '>=0.4.0'}
|
||||||
dev: true
|
|
||||||
|
|
||||||
/delegates/1.0.0:
|
/delegates/1.0.0:
|
||||||
resolution: {integrity: sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==}
|
resolution: {integrity: sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==}
|
||||||
|
|
@ -2951,6 +2982,16 @@ packages:
|
||||||
resolution: {integrity: sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA==}
|
resolution: {integrity: sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/follow-redirects/1.15.9:
|
||||||
|
resolution: {integrity: sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==}
|
||||||
|
engines: {node: '>=4.0'}
|
||||||
|
peerDependencies:
|
||||||
|
debug: '*'
|
||||||
|
peerDependenciesMeta:
|
||||||
|
debug:
|
||||||
|
optional: true
|
||||||
|
dev: false
|
||||||
|
|
||||||
/foreground-child/3.3.0:
|
/foreground-child/3.3.0:
|
||||||
resolution: {integrity: sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==}
|
resolution: {integrity: sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==}
|
||||||
engines: {node: '>=14'}
|
engines: {node: '>=14'}
|
||||||
|
|
@ -2988,7 +3029,6 @@ packages:
|
||||||
asynckit: 0.4.0
|
asynckit: 0.4.0
|
||||||
combined-stream: 1.0.8
|
combined-stream: 1.0.8
|
||||||
mime-types: 2.1.35
|
mime-types: 2.1.35
|
||||||
dev: true
|
|
||||||
|
|
||||||
/formidable/2.1.2:
|
/formidable/2.1.2:
|
||||||
resolution: {integrity: sha512-CM3GuJ57US06mlpQ47YcunuUZ9jpm8Vx+P2CGt2j7HpgkKZO/DJYQ0Bobim8G6PFQmK5lOqOOdUXboU+h73A4g==}
|
resolution: {integrity: sha512-CM3GuJ57US06mlpQ47YcunuUZ9jpm8Vx+P2CGt2j7HpgkKZO/DJYQ0Bobim8G6PFQmK5lOqOOdUXboU+h73A4g==}
|
||||||
|
|
@ -4438,6 +4478,10 @@ packages:
|
||||||
set-blocking: 2.0.0
|
set-blocking: 2.0.0
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/oauth/0.10.0:
|
||||||
|
resolution: {integrity: sha512-1orQ9MT1vHFGQxhuy7E/0gECD3fd2fCC+PIX+/jgmU/gI3EpRocXtmtvxCO5x3WZ443FLTLFWNDjl5MPJf9u+Q==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/object-assign/4.1.1:
|
/object-assign/4.1.1:
|
||||||
resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==}
|
resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
|
|
@ -4567,6 +4611,13 @@ packages:
|
||||||
resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==}
|
resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==}
|
||||||
engines: {node: '>= 0.8'}
|
engines: {node: '>= 0.8'}
|
||||||
|
|
||||||
|
/passport-github2/0.1.12:
|
||||||
|
resolution: {integrity: sha512-3nPUCc7ttF/3HSP/k9sAXjz3SkGv5Nki84I05kSQPo01Jqq1NzJACgMblCK0fGcv9pKCG/KXU3AJRDGLqHLoIw==}
|
||||||
|
engines: {node: '>= 0.8.0'}
|
||||||
|
dependencies:
|
||||||
|
passport-oauth2: 1.8.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
/passport-jwt/4.0.1:
|
/passport-jwt/4.0.1:
|
||||||
resolution: {integrity: sha512-UCKMDYhNuGOBE9/9Ycuoyh7vP6jpeTp/+sfMJl7nLff/t6dps+iaeE0hhNkKN8/HZHcJ7lCdOyDxHdDoxoSvdQ==}
|
resolution: {integrity: sha512-UCKMDYhNuGOBE9/9Ycuoyh7vP6jpeTp/+sfMJl7nLff/t6dps+iaeE0hhNkKN8/HZHcJ7lCdOyDxHdDoxoSvdQ==}
|
||||||
dependencies:
|
dependencies:
|
||||||
|
|
@ -4581,6 +4632,17 @@ packages:
|
||||||
passport-strategy: 1.0.0
|
passport-strategy: 1.0.0
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/passport-oauth2/1.8.0:
|
||||||
|
resolution: {integrity: sha512-cjsQbOrXIDE4P8nNb3FQRCCmJJ/utnFKEz2NX209f7KOHPoX18gF7gBzBbLLsj2/je4KrgiwLLGjf0lm9rtTBA==}
|
||||||
|
engines: {node: '>= 0.4.0'}
|
||||||
|
dependencies:
|
||||||
|
base64url: 3.0.1
|
||||||
|
oauth: 0.10.0
|
||||||
|
passport-strategy: 1.0.0
|
||||||
|
uid2: 0.0.4
|
||||||
|
utils-merge: 1.0.1
|
||||||
|
dev: false
|
||||||
|
|
||||||
/passport-strategy/1.0.0:
|
/passport-strategy/1.0.0:
|
||||||
resolution: {integrity: sha512-CB97UUvDKJde2V0KDWWB3lyf6PC3FaZP7YxZ2G8OAtn9p4HI9j9JLP9qjOGZFvyl8uwNT8qM+hGnz/n16NI7oA==}
|
resolution: {integrity: sha512-CB97UUvDKJde2V0KDWWB3lyf6PC3FaZP7YxZ2G8OAtn9p4HI9j9JLP9qjOGZFvyl8uwNT8qM+hGnz/n16NI7oA==}
|
||||||
engines: {node: '>= 0.4.0'}
|
engines: {node: '>= 0.4.0'}
|
||||||
|
|
@ -4710,6 +4772,10 @@ packages:
|
||||||
forwarded: 0.2.0
|
forwarded: 0.2.0
|
||||||
ipaddr.js: 1.9.1
|
ipaddr.js: 1.9.1
|
||||||
|
|
||||||
|
/proxy-from-env/1.1.0:
|
||||||
|
resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/punycode/2.3.1:
|
/punycode/2.3.1:
|
||||||
resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==}
|
resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==}
|
||||||
engines: {node: '>=6'}
|
engines: {node: '>=6'}
|
||||||
|
|
@ -5567,6 +5633,10 @@ packages:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@lukeed/csprng': 1.1.0
|
'@lukeed/csprng': 1.1.0
|
||||||
|
|
||||||
|
/uid2/0.0.4:
|
||||||
|
resolution: {integrity: sha512-IevTus0SbGwQzYh3+fRsAMTVVPOoIVufzacXcHPmdlle1jUpq7BRL+mw3dgeLanvGZdwwbWhRV6XrcFNdBmjWA==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/undici-types/6.19.8:
|
/undici-types/6.19.8:
|
||||||
resolution: {integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==}
|
resolution: {integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
import { Test, TestingModule } from '@nestjs/testing';
|
|
||||||
import { AppController } from './app.controller';
|
|
||||||
import { AppService } from './app.service';
|
|
||||||
|
|
||||||
describe('AppController', () => {
|
|
||||||
let appController: AppController;
|
|
||||||
|
|
||||||
beforeEach(async () => {
|
|
||||||
const app: TestingModule = await Test.createTestingModule({
|
|
||||||
controllers: [AppController],
|
|
||||||
providers: [AppService],
|
|
||||||
}).compile();
|
|
||||||
|
|
||||||
appController = app.get<AppController>(AppController);
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('root', () => {
|
|
||||||
it('should return "Hello World!"', () => {
|
|
||||||
expect(appController.getHello()).toBe('Hello World!');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
@ -5,6 +5,8 @@ import { ConfigModule, ConfigService } from '@nestjs/config';
|
||||||
import { AppService } from './app.service';
|
import { AppService } from './app.service';
|
||||||
import { UserModule } from './user/user.module';
|
import { UserModule } from './user/user.module';
|
||||||
import { User } from './user/entities/user.entity';
|
import { User } from './user/entities/user.entity';
|
||||||
|
import { AuthModule } from './auth/auth.module';
|
||||||
|
import { LarkModule } from './lark/lark.module';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
|
|
@ -25,6 +27,8 @@ import { User } from './user/entities/user.entity';
|
||||||
}),
|
}),
|
||||||
TypeOrmModule.forFeature([User]),
|
TypeOrmModule.forFeature([User]),
|
||||||
UserModule,
|
UserModule,
|
||||||
|
AuthModule,
|
||||||
|
LarkModule,
|
||||||
],
|
],
|
||||||
controllers: [AppController],
|
controllers: [AppController],
|
||||||
providers: [AppService],
|
providers: [AppService],
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
import { Controller, Get, Req, Res, UseGuards } from '@nestjs/common';
|
||||||
|
import { AuthGuard } from '@nestjs/passport';
|
||||||
|
import { Response } from 'express';
|
||||||
|
|
||||||
|
@Controller('auth')
|
||||||
|
export class AuthController {
|
||||||
|
@Get('github')
|
||||||
|
@UseGuards(AuthGuard('github'))
|
||||||
|
async githubLogin() {
|
||||||
|
// GitHub 登录重定向
|
||||||
|
}
|
||||||
|
|
||||||
|
@Get('github/callback')
|
||||||
|
@UseGuards(AuthGuard('github'))
|
||||||
|
async githubCallback(@Req() req, @Res() res: Response) {
|
||||||
|
const user = req.user;
|
||||||
|
|
||||||
|
// 构造前端 URL,附带用户信息或 Token
|
||||||
|
const frontendUrl = `http://localhost:8000/?username=${user.username}&email=${user.email}`;
|
||||||
|
// 重定向到前端
|
||||||
|
return res.redirect(frontendUrl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
import { Module } from '@nestjs/common';
|
||||||
|
import { PassportModule } from '@nestjs/passport';
|
||||||
|
import { AuthController } from './auth.controller';
|
||||||
|
import { GitHubStrategy } from './github.strategy';
|
||||||
|
|
||||||
|
@Module({
|
||||||
|
imports: [PassportModule],
|
||||||
|
controllers: [AuthController],
|
||||||
|
providers: [GitHubStrategy],
|
||||||
|
})
|
||||||
|
export class AuthModule {}
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class AuthService {}
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
import { PassportStrategy } from '@nestjs/passport';
|
||||||
|
import { Strategy } from 'passport-github2';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class GitHubStrategy extends PassportStrategy(Strategy, 'github') {
|
||||||
|
constructor() {
|
||||||
|
super({
|
||||||
|
clientID: process.env.GITHUB_CLIENT_ID, // 从环境变量加载
|
||||||
|
clientSecret: process.env.GITHUB_CLIENT_SECRET,
|
||||||
|
callbackURL: process.env.GITHUB_CALLBACK_URL, // 回调 URL
|
||||||
|
scope: ['user:email'], // 需要的权限
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async validate(accessToken: string, refreshToken: string, profile: any) {
|
||||||
|
// 返回用户信息,或者直接处理用户登录逻辑
|
||||||
|
const { id, username, emails } = profile;
|
||||||
|
return {
|
||||||
|
id,
|
||||||
|
username,
|
||||||
|
email: emails?.[0]?.value || null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
import { Controller, Get, Query, Res } from '@nestjs/common';
|
||||||
|
import { LarkService } from './lark.service';
|
||||||
|
import { Response } from 'express';
|
||||||
|
|
||||||
|
@Controller('lark')
|
||||||
|
export class LarkController {
|
||||||
|
constructor(private readonly larkService: LarkService) {}
|
||||||
|
|
||||||
|
@Get('login')
|
||||||
|
async login(@Query('redirectUri') redirectUri: string, @Res() res: Response) {
|
||||||
|
const loginUrl = await this.larkService.getLoginUrl(redirectUri);
|
||||||
|
return res.redirect(loginUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Get('callback')
|
||||||
|
async callback(@Query('code') code: string, @Res() res: Response) {
|
||||||
|
if (!code) {
|
||||||
|
return res.status(400).send('Authorization code is missing');
|
||||||
|
}
|
||||||
|
|
||||||
|
const tokenData = await this.larkService.getAccessToken(code);
|
||||||
|
|
||||||
|
if (tokenData && tokenData.code === 0) {
|
||||||
|
const user = tokenData.data;
|
||||||
|
return res.json({ message: 'Login successful', user });
|
||||||
|
} else {
|
||||||
|
return res.status(400).send('Failed to retrieve access token');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
import { Module } from '@nestjs/common';
|
||||||
|
import { LarkService } from './lark.service';
|
||||||
|
import { LarkController } from './lark.controller';
|
||||||
|
|
||||||
|
@Module({
|
||||||
|
controllers: [LarkController],
|
||||||
|
providers: [LarkService],
|
||||||
|
})
|
||||||
|
export class LarkModule {}
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
import axios from 'axios';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class LarkService {
|
||||||
|
private readonly appId = process.env.FEISHU_APP_ID;
|
||||||
|
private readonly appSecret = process.env.FEISHU_APP_SECRET;
|
||||||
|
|
||||||
|
async getLoginUrl(redirectUri: string): Promise<string> {
|
||||||
|
return `https://open.feishu.cn/open-apis/authen/v1/index?app_id=${this.appId}&redirect_uri=${encodeURIComponent(
|
||||||
|
redirectUri,
|
||||||
|
)}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
async getAccessToken(authCode: string): Promise<any> {
|
||||||
|
const url = 'https://open.feishu.cn/open-apis/authen/v1/access_token';
|
||||||
|
const data = {
|
||||||
|
grant_type: 'authorization_code',
|
||||||
|
code: authCode,
|
||||||
|
app_id: this.appId,
|
||||||
|
app_secret: this.appSecret,
|
||||||
|
};
|
||||||
|
|
||||||
|
const response = await axios.post(url, data);
|
||||||
|
return response.data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -2,6 +2,9 @@ import { NestFactory } from '@nestjs/core';
|
||||||
import { AppModule } from './app.module';
|
import { AppModule } from './app.module';
|
||||||
import * as mysql from 'mysql2/promise';
|
import * as mysql from 'mysql2/promise';
|
||||||
import { ConfigService } from '@nestjs/config';
|
import { ConfigService } from '@nestjs/config';
|
||||||
|
import * as dotenv from 'dotenv';
|
||||||
|
|
||||||
|
dotenv.config();
|
||||||
|
|
||||||
async function bootstrap() {
|
async function bootstrap() {
|
||||||
// 启动 Nest 应用
|
// 启动 Nest 应用
|
||||||
|
|
|
||||||
|
|
@ -1,20 +0,0 @@
|
||||||
import { Test, TestingModule } from '@nestjs/testing';
|
|
||||||
import { UserController } from './user.controller';
|
|
||||||
import { UserService } from './user.service';
|
|
||||||
|
|
||||||
describe('UserController', () => {
|
|
||||||
let controller: UserController;
|
|
||||||
|
|
||||||
beforeEach(async () => {
|
|
||||||
const module: TestingModule = await Test.createTestingModule({
|
|
||||||
controllers: [UserController],
|
|
||||||
providers: [UserService],
|
|
||||||
}).compile();
|
|
||||||
|
|
||||||
controller = module.get<UserController>(UserController);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should be defined', () => {
|
|
||||||
expect(controller).toBeDefined();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
Loading…
Reference in New Issue